2010-12-02 10 views
-1

J'ai quelques données bien structurées qui ressemble à ceci:Fusionner pour cibler des colonnes en utilisant des lignes source?

CREATE TABLE SourceBodyPartColors 
(
person_ID INTEGER NOT NULL, 
body_part_name VARCHAR(5) NOT NULL 
    CHECK (body_part_name IN ('hair', 'eye', 'teeth')), 
color VARCHAR(20) NOT NULL, 
UNIQUE (color, body_part_name, person_ID) 
); 

INSERT INTO SourceBodyPartColors (person_ID, body_part_name, color) 
    VALUES (1, 'eye', 'blue'), 
      (1, 'hair', 'blond'), 
      (1, 'teeth', 'white'), 
      (2, 'hair', 'white'), 
      (2, 'teeth', 'yellow'), 
      (3, 'hair', 'red'); 

Malheureusement, la structure cible est pas si belle, et ressemble plus à ceci:

CREATE TABLE TargetBodyPartColors 
(
person_ID INTEGER NOT NULL UNIQUE, 
eye_color VARCHAR(20), 
hair_color VARCHAR(20), 
teeth_color VARCHAR(20) 
); 

INSERT INTO TargetBodyPartColors (person_ID) 
    VALUES (1), (2), (3); 

Je peux écrire un SQL- 92 UPDATE comme ceci:

UPDATE TargetBodyPartColors 
    SET eye_color = (
        SELECT S1.color 
         FROM SourceBodyPartColors AS S1 
        WHERE S1.person_ID 
           = TargetBodyPartColors.person_ID 
          AND S1.body_part_name = 'eye' 
        ), 
     hair_color = (
        SELECT S1.color 
         FROM SourceBodyPartColors AS S1 
         WHERE S1.person_ID 
           = TargetBodyPartColors.person_ID 
          AND S1.body_part_name = 'hair' 
        ), 
     teeth_color = (
         SELECT S1.color 
         FROM SourceBodyPartColors AS S1 
         WHERE S1.person_ID 
           = TargetBodyPartColors.person_ID 
          AND S1.body_part_name = 'teeth' 
        ); 

... mais le code répété me dérange.

Un bon canidate pour simplifier en utilisant MERGE, je pensais, mais je ne peux pas arriver à quelque chose de raisonnable. Toutes les idées pour utiliser MERGE avec ces données. (Note: Je veux éviter le propriétaire UPDATE..FROM syntax, merci.)

+2

Êtes-vous heureux en utilisant 'PIVOT'? –

+0

AFAIK, MERGE est SQL: 2003, est-ce vraiment mieux? – Unreason

+0

@marc_s: Je peux voir pourquoi vous pourriez penser que c'est EAV mais ce n'est pas le cas. Voir l'article de Wikipedia sur la première forme normale (http://en.wikipedia.org/wiki/First_normal_form): la structure 'Target' est semblable à la table 'Customer' présentée dans la sous-section 'Répétition des groupes à travers les colonnes' (ie 1NF violation). La structure "Source" est plus proche du tableau "Customer Telephone Table" présenté sous le sous-titre "Un design conforme à 1NF". – onedaywhen

Répondre

6
WITH Pivoted AS 
(
    SELECT person_ID, eye, hair, teeth 
    FROM SourceBodyPartColors 
    PIVOT 
    (
    MAX (color) FOR body_part_name IN ([eye], [hair], [teeth]) 
    ) AS pvt 
) 
MERGE TargetBodyPartColors AS target 
USING Pivoted AS source 
ON (target.person_ID = source.person_ID) 
WHEN MATCHED THEN 
UPDATE SET eye_color = source.eye, 
      hair_color = source.hair, 
      teeth_color = source.teeth ; 
Questions connexes