2010-07-15 7 views
0

J'ai une instruction SQL Select où je dois retourner certaines valeurs en fonction d'une condition. J'ai besoin de renvoyer plusieurs valeurs à chaque fois, mais ma compréhension de l'instruction Case est que vous ne pouvez renvoyer qu'une seule valeur pour chaque cas. Je suis en train de contourner ce problème en utilisant les instructions UNION pour le moment, mais tout semble un peu lourd - y at-il une meilleure façon de faire cela? Fondamentalement, j'ai un tas d'invites, chacune avec une réponse de "Oui", "Non" ou "Dans l'avenir" (J'ai effectivement plus de réponses, mais je vais juste utiliser 3 pour l'exemple pour le garder court!) - J'ai besoin de produire une colonne pour chaque type de réponse, avec 1 comme valeur pour la réponse appropriée, et 0 pour tous les autres. Il est sans doute plus faciles à comprendre si vous regardez le SQL ...SQL Server - Définition de plusieurs valeurs dans une instruction de requête?

requête Ma (simplifiée) ressemble à ceci:

SELECT branch, 
     promptType, 
     response, 
     1 AS 'Yes', 
     0 AS 'No', 
     0 AS 'Not Discussed' 
FROM prompts 
WHERE response = 'Y' 

UNION 

SELECT branch, 
     promptType, 
     response, 
     0 AS 'Yes', 
     1 AS 'No', 
     0 AS 'Not Discussed' 
FROM prompts 
WHERE response = 'N' 

UNION 

SELECT branch, 
     promptType, 
     response, 
     0 AS 'Yes', 
     0 AS 'No', 
     1 AS 'Not Discussed' 
FROM prompts 
WHERE response = 'D' 

Répondre

3

Avez-vous envisagé de créer une table de décodage pour les réponses, et de vous joindre à cela?

Par exemple, cela créerait une table pour décoder les réponses:

CREATE TABLE decoder (response CHAR(1), [Yes] BIT, [No] BIT, [Not Discussed] BIT) 
INSERT INTO decoder VALUES ('Y', 1, 0, 0) 
INSERT INTO decoder VALUES ('N', 0, 1, 0) 
INSERT INTO decoder VALUES ('D', 0, 0, 1) 

... et vous pourriez alors se joindre à elle pour obtenir des résultats similaires (? Le même) que vous obtenez avec votre UNION:

SELECT 
    prompts.branch, 
    prompts.prompttype, 
    prompts.response, 
    decoder.yes, 
    decoder.no, 
    decoder.[Not Discussed] 
FROM 
    prompts INNER JOIN decoder ON prompts.response = decoder.response 

Peut-être une approche qui mérite d'être considérée; c'est une solution plus relationnelle que votre syndicat, et probablement plus facile à maintenir.

+0

Intéressant, je vais essayer! N'a pas pensé à cela, merci :-) – TabbyCool

+0

Acceptée comme meilleure réponse, la requête qui en résulte est beaucoup plus maintenable que ce que j'avais à l'origine. – TabbyCool

4

Quelque chose comme ...

SELECT branch, 
     prompttype, 
     CASE WHEN response = 'Y' THEN 'Yes' 
      WHEN response = 'N' THEN 'No' 
      WHEN response = 'D' THEN 'Not Discussed' 
    FROM prompts; 

peut-être ce que vous sont après.

Après votre commentaire, peut-être ...

SELECT branch, 
     prompttype, 
     CASE WHEN response = 'Y' THEN 1 ELSE 0 AS Yes, 
     CASE WHEN response = 'N' THEN 1 ELSE 0 AS No, 
     CASE WHEN response = 'D' THEN 1 ELSE 0 AS Not_Discussed 
    FROM prompts; 

pourrait le faire.

+0

Je dois retourner les 3 réponses à chaque fois, juste avec la valeur 0 ou 1. Ainsi, les valeurs d'invite ("Oui", "Non", "Non discuté") seraient en réalité des en-têtes de colonne et chaque enregistrement aurait un 0 ou un 1 dans chaque champ. La sortie que je reçois de l'instruction UNION dans mon article original est en fait la sortie correcte, je pensais juste qu'il pourrait y avoir une meilleure façon de le produire. – TabbyCool

+0

Ah. Je vois. Je vais y réfléchir un peu plus alors. –

+0

Merci :-) Essentiellement, je dois être en mesure de définir les valeurs des colonnes "Oui", "Non" et "Non discuté" pour chaque ligne de l'instruction Case, mais je ne suis pas sûr que cela soit possible . Pourrait-il être fait avec une instruction If à la place? Si ce n'est pas le cas, le syndicat n'aura qu'à le faire, il se sent juste comme beaucoup de duplication. – TabbyCool

0
SELECT branch, 
     prompttype, 
    response, 
     CASE WHEN response = 'Y' THEN 1 ELSE 0 END AS Yes, 
     CASE WHEN response = 'N' THEN 1 ELSE 0 END AS [No], 
     CASE WHEN response = 'D' THEN 1 ELSE 0 END AS Not_Discussed 
    FROM prompts; 
+0

C'est la même chose que la réponse de Brian - elle ne produit pas la sortie requise. – TabbyCool

0

Si ce projet de déclaration CASE de la vôtre a retourné des valeurs multiples dans une seule colonne, quel serait le type de données soit: un tableau, une liste, une table, un document XML, un objet métier, etc? Pour un système de gestion de base de données véritablement relationnel (TRDBMS), la réponse serait une variable relationnelle. Mais nous parlons de SQL Server, ici.

Je pense que la réponse que vous recherchez est que les types de données de SQL Server sont scalaires et non multivalués.

+0

Je ne veux pas plusieurs valeurs dans une seule colonne, je veux retourner plusieurs colonnes, mais avoir leurs valeurs définies dans l'instruction case afin que la sortie soit la même que celle produite par ma requête d'origine. – TabbyCool

1

Vous devez ajouter le groupement, je pense. Je l'ai fait avec des projections trimestrielles. Si vous disposez d'un identifiant unique pour chaque réponse, ce serait quelque chose comme ça (sinon il choisira max pour toute la branche/prompttype/réponse):

SELECT uniqueID, 
    branch, 
    prompttype, 
    response, 
    MAX(CASE WHEN response = 'Y' THEN 1 ELSE 0 END) AS Yes, 
    MAX(CASE WHEN response = 'N' THEN 1 ELSE 0 END) AS [No], 
    MAX(CASE WHEN response = 'D' THEN 1 ELSE 0 END) AS Not_Discussed 
FROM prompts 

GROUP BY uniqueID, 
    branch, 
    prompttype, 
    response;