2009-09-09 5 views
4

J'ai une requête qui renvoie un jeu de résultats similaire à celui ci-dessousComment obtenir des valeurs distinctes des colonnes?

 A | B | C | D 
    -----|----|----|----- 
1 abc | d0 | e0 | true 
2 def | d0 | e1 | true 
3 ghi | d0 | e2 | true 
4 jkl | d1 | e1 | true 
5 mno | d2 | e2 | false 

Dans la colonne A chaque valeur est unique. mais les colonnes B, C, D ont des valeurs en double. Je veux toutes les valeurs de la colonne A mais les valeurs distinctes de la colonne B, C, D.

résultat attendu est quelque chose comme ça

 A | B | C | D 
    -----|---- |---- |----- 
1 abc | d0 | e0 | true 
2 def | NULL| e1 | NULL 
3 ghi | NULL| NULL| NULL 
4 jkl | d1 | NULL| NULL 
5 mno | d2 | e2 | false 

La seule contrainte est que je veux atteindre cet objectif dans une instruction select unique. Aucune instruction Select imbriquée.

+1

Pourquoi 'C' est' null' dans la ligne '3'? – Quassnoi

Répondre

1
SELECT A, 
     CASE 
     WHEN EXISTS 
       (
       SELECT NULL 
       FROM mytable mi 
       WHERE mi.id < mo.id 
         AND mi.b = mo.b 
       ) THEN NULL 
     ELSE B 
     END AS B, 
     CASE 
     WHEN EXISTS 
       (
       SELECT NULL 
       FROM mytable mi 
       WHERE mi.id < mo.id 
         AND mi.c = mo.c 
       ) THEN NULL 
     ELSE c 
     END AS c, 
     CASE 
     WHEN EXISTS 
       (
       SELECT NULL 
       FROM mytable mi 
       WHERE mi.id < mo.id 
         AND mi.d = mo.d 
       ) THEN NULL 
     ELSE d 
     END AS d 
FROM mytable mo 
+0

Oui, quelque chose comme ça. N'oubliez pas de mettre les filtres non seulement à la clause from de la requête externe, mais aussi à toutes les sous-requêtes. –

+1

Vous avez besoin d'une clause order by où vous commandez par A, B, C, D. Si vous commandez d'une manière différente, la ligne où la seule valeur de B, C ou D apparaît peut ne pas être la première rangée. Ensuite, vous ne savez pas quelle valeur avait été là. –

+0

d'où vient la colonne "id"? pour moi, il semble que l'OP affiche juste les numéros de ligne (pas de nom de colonne ou de tirets) –

0

Ce dont vous avez besoin est en fait contre la nature de sql. En sql, le résultat ne dépend pas de la commande.

Même si vous trouvez un moyen d'obtenir un résultat comme celui-ci (par exemple, tel que fourni par Quassnoi), j'éviterais de le faire en SQL.

+0

Je ne suis pas d'accord, si vous pouvez le faire dans la requête, faites-le. Regardez ma réponse pour voir à quel point c'est facile à réaliser. Il n'est pas beaucoup plus difficile qu'un select régulier de la table, en utilisant row_number() pour trouver la première occurrence de chaque valeur. –

+0

Juste parce que vous pouvez ne signifie pas que vous devriez. Vous devez également tenir compte des performances, de la maintenabilité, etc. "can" = "should" est trop niaive. A MON HUMBLE AVIS. – MatBailie

+0

@Dems, traite l'ensemble en SQL ou en boucle dans l'application cliente? Lorsque cela est possible, j'aime traiter l'ensemble en SQL, et c'est le cas avec cette requête. –

3

essayez ceci:

DECLARE @YourTable table (A char(3), B char(2), C char(2), D varchar(5)) 
INSERT INTO @YourTable VALUES ('abc','d0','e0','true') 
INSERT INTO @YourTable VALUES ('def','d0','e1','true') 
INSERT INTO @YourTable VALUES ('ghi','d0','e2','true') 
INSERT INTO @YourTable VALUES ('jkl','d1','e1','true') 
INSERT INTO @YourTable VALUES ('mno','d2','e2','false') 


SELECT 
    A 
    ,CASE WHEN ROW_NUMBER() OVER(PARTITION BY B ORDER BY A,B)=1 THEN B ELSE NULL END AS B 
    ,CASE WHEN ROW_NUMBER() OVER(PARTITION BY C ORDER BY A,C)=1 THEN C ELSE NULL END AS C 
    ,CASE WHEN ROW_NUMBER() OVER(PARTITION BY D ORDER BY A,D)=1 THEN D ELSE NULL END AS D 
    FROM @YourTable 
    ORDER BY A,B,C,D 

SORTIE:

A B C D 
---- ---- ---- ----- 
abc d0 e0 true 
def NULL e1 NULL 
ghi NULL e2 NULL 
jkl d1 NULL NULL 
mno d2 NULL false 

(5 row(s) affected) 
Questions connexes