2011-08-26 10 views
2

Je suis en train de faire quelque chose de similaire à How can I improve this SQL query?avec la logique de procédure stockée

Cependant, il y a une logique Essentiellement j'ai une liste d'ID qui pourraient avoir plusieurs valeurs qui leur sont associées, les valeurs étant Oui, Non ou une autre chaîne Pour l'ID x, si l'une des valeurs est un Oui, x doit être Oui, si elles sont toutes Non, il doit être Non, si elles contiennent d'autres valeurs mais oui et non, afficher cette valeur. Je veux seulement retourner 1 ligne par ID, pas de doublons.

mais dans ma logique si toutes les valeurs sont oui, afficher oui, si toutes les valeurs sont affichent pas alors non, si elle est un mélange de oui, non ou quoi que ce soit l'affichage autre mélange

DECLARE @tempTable table (ID int, Val varchar(1)) 

    INSERT INTO @tempTable (ID, Val) VALUES (10, 'Y') 
    INSERT INTO @tempTable (ID, Val) VALUES (11, 'N') 
    INSERT INTO @tempTable (ID, Val) VALUES (11, 'N') 
    INSERT INTO @tempTable (ID, Val) VALUES (12, 'Y') 
    INSERT INTO @tempTable (ID, Val) VALUES (12, 'Y') 
    INSERT INTO @tempTable (ID, Val) VALUES (12, 'Y') 
    INSERT INTO @tempTable (ID, Val) VALUES (13, 'N') 
    INSERT INTO @tempTable (ID, Val) VALUES (14, 'Y') 
    INSERT INTO @tempTable (ID, Val) VALUES (14, 'N') 
    INSERT INTO @tempTable (ID, Val) VALUES (15, 'Y') 
    INSERT INTO @tempTable (ID, Val) VALUES (16, 'Y') 
    INSERT INTO @tempTable (ID, Val) VALUES (17, 'F') 
    INSERT INTO @tempTable (ID, Val) VALUES (18, 'P') 


    SELECT DISTINCT t.ID, COALESCE(t2.Val, t3.Val, t4.Val) 
    FROM @tempTable t 
    LEFT JOIN 
    (
     SELECT ID, Val 
     FROM @tempTable 
     WHERE Val = 'Y' 
    ) t2 ON t.ID = t2.ID 
    LEFT JOIN 
    (
     SELECT 
     ID, Val FROM @tempTable 
     WHERE Val = 'N' 
    ) t3 ON t.ID = t3.ID 
    LEFT JOIN 
    (
     SELECT ID, Val 
     FROM @tempTable 
     WHERE Val <> 'Y' AND Val <> 'N' 
    ) t4 ON t.ID = t4.ID 

Update dbo.households 
SET dbo.households.code = #TempTable.code 
FROM #TempTable 
WHERE dbo.households.id = #TempTable.id 
+1

quelle est la question? – akonsu

+0

pour une raison quelconque, si un résultat vient comme N, N, P il montre encore N ou s'il sort Y, N il montrera Y. Je veux Y, Y pour sortir comme Y et N, N pour sortir comme N et tout le reste à sortir comme 'M' –

Répondre

5
SELECT ID , 
     CASE WHEN MAX(Val) = MIN(Val) 
        AND MAX(Val) IN ('N', 'Y') THEN MAX(Val) 
      ELSE 'M' 
     END 
FROM @tempTable 
GROUP BY ID 

Ou une version qui retourne Y si une existe plutôt que si tous sont Y

SELECT ID , 
     ISNULL(MAX(CASE WHEN Val = 'Y' THEN 'Y' END), 
       CASE WHEN MAX(Val) = MIN(Val) THEN MAX(Val) 
           ELSE 'M' 
         END) 
FROM @tempTable 
GROUP BY ID 

Ou une version finale qui prend littéralement « si elles contiennent d'autres valeurs, mais oui et non, affichage cette valeur. " déclaration.

SELECT ID , 
     ISNULL(MAX(CASE WHEN Val = 'Y' THEN 'Y'END), 
       ISNULL(MAX(CASE WHEN Val NOT IN ('N', 'Y') THEN Val END), 
         MAX(Val))) 
FROM @tempTable 
GROUP BY ID 
+0

+1 - Solution très simple! – JNK

+0

D'où vient le 'M'?Sa question indiquait que «si elles contiennent d'autres valeurs mais oui et non, ** afficher cette valeur **». De plus, vous vérifiez seulement que la valeur maximum est 'Y' ou 'N' ... et ne vérifie pas vraiment les autres valeurs potentielles. 'P' évaluera plus haut que 'N' mais moins que 'Y'. – canon

+0

@ Martin, cela semble toujours éteint. Vous devez déterminer les Y/N séparément des autres valeurs ... Votre solution actuelle est cassée et renvoie un 'M' (plutôt que 'Y') pour l'ID 14. – canon

2

Vous peut faire usage de max() puisque c'est une valeur de char. Donnez ce un tourbillon:

Note: La logique employée ici est que les non-Y/N> Tous Y> Seulement N

[Modifier] Refonte & simplifié:

select 
t.ID 
,isnull(max(nyn.Val),max(yn.Val)) as Val 
from @tempTable as t  
    left join @tempTable as nyn -- Non-Y/N value 
    on nyn.ID = t.ID 
    and nyn.Val not in ('Y','N') 
    left join @tempTable as yn -- Y/N value 
    on yn.ID = t.ID 
    and yn.Val in ('Y','N') 
group by t.ID 

donne les résultats suivants:

ID Val 
10 Y 
11 N 
12 Y 
13 N 
14 Y 
15 Y 
16 Y 
17 F 
18 P 
+0

merci, mais pour une raison quelconque, ma déclaration de mise à jour ne fonctionne pas, mais le résultat lorsque j'exécute la requête est. Donc, fondamentalement, je reçois des résultats corrects maintenant, mais ma requête de mise à jour me donne les anciennes valeurs –

+0

Ma solution va toujours retourner plusieurs enregistrements pour les ID ayant plus d'une valeur non-Y/N ... donc vous pouvez décider quelle logique vous aimeriez postuler pour filtrer plusieurs hits. – canon

+0

ahh donc si un enregistrement a à la fois un y et un n vous retournerez les deux lignes? –

0

Une autre façon de le faire. J'utilise MAX() dans le cas où plus d'une valeur de retour autre que Y et N

SELECT 
    ID, 
    CASE 
    WHEN EXISTS(SELECT 1 FROM @tempTable tt WHERE t.ID = tt.ID AND tt.Val = 'Y') 
      THEN 'Y' 
    WHEN EXISTS(SELECT 1 FROM @tempTable tt WHERE t.ID = tt.ID AND tt.Val NOT IN ('Y','N')) 
      THEN (SELECT MAX(Val) FROM @tempTable tt WHERE t.ID = tt.ID AND tt.Val NOT IN ('Y','N')) 
    ELSE 'N' 
    END   
FROM @tempTable t 
GROUP BY ID 
Questions connexes