2010-04-29 1 views
2

Désolé pour le titre boiteux, mes compétences descriptives sont pauvres aujourd'hui.SQL Server, comment joindre une table dans un format "pivoté" (renvoyer des colonnes au lieu de lignes)?

En un mot, j'ai une requête similaire à ce qui suit:

SELECT P.LAST_NAME, P.FIRST_NAME, D.DEMO_GROUP 
FROM PERSON P 
JOIN PERSON_DEMOGRAPHIC PD ON PD.PERSON_ID = P.PERSON_ID 
JOIN DEMOGRAPHIC D ON D.DEMOGRAPHIC_ID = PD.DEMOGRAPHIC_ID 

Cette retourne sortie comme ceci:

LAST_NAME  FIRST_NAME  DEMO_GROUP 
--------------------------------------------- 
Johnson  Bob   Male 
Smith   Jane   Female 
Smith   Jane   Teacher 
Beeblebrox  Zaphod   Male 
Beeblebrox  Zaphod   Alien 
Beeblebrox  Zaphid   Politician 

Je préfère la sortie soit similaire à ce qui suit:

LAST_NAME  FIRST_NAME  Male   Female   Teacher  Alien   Politician 
--------------------------------------------------------------------------------------------------------- 
Johnson  Bob   1    0    0    0    0 
Smith   Jane   0    1    1    0    0 
Beeblebrox  Zaphod   1    0    0    1    1 

Le nombre de lignes dans le tableau DEMOGRAPHIC varie, donc je ne peux pas dire avec certitude comment beaucoup de colonnes dont j'ai besoin. La requête doit être flexible.

Oui, il serait trivial de le faire dans le code. Mais cette requête est un élément d'un ensemble complexe de procédures stockées, de vues et de services de génération de rapports, dont beaucoup sont en dehors de ma sphère d'influence. J'ai besoin de produire cette sortie dans la base de données pour éviter de casser le système. Des idées?

Il s'agit en fait de MS SQL Server 2005.

Merci.

+4

Astuce: Jetez un oeil à PIVOT http://msdn.microsoft.com/en-us/library/ms177410.aspx –

+0

Les requêtes dans ces réponses vous obtiendrez sur la bonne voie: http: // stackoverflow.com/questions/2433445/sql-join-problem/2433561#2433561 – AaronLS

Répondre

3

Vous pouvez utiliser la fonction PIVOT. Voici un morceau de code. Cette fonction nécessite les colonnes à l'avance, mais si vous ne connaissez pas le nombre de colonnes, vous devez créer une requête SQL dynamique. Jetez un oeil à this réponse.

SELECT LAST_NAME, FIRST_NAME, [Male], [Female], [Alien], [Politician], [Teacher] 
FROM 
(SELECT LAST_NAME, FIRST_NAME, DEMO_GROUP 
FROM Person) p 
PIVOT 
(
COUNT (DEMO_GROUP) 
FOR DEMO_GROUP IN 
([Male], [Female], [Alien], [Politician], [Teacher]) 
) AS pvt 
ORDER BY LAST_NAME 
+0

Merci. Je suppose qu'il n'y a aucun moyen d'éviter l'utilisation de SQL dynamique si vous ne connaissez pas les colonnes à l'avance. Heureusement, j'ai trouvé un moyen de le faire en SQL après tout (même si c'est encore désordonné!). J'apprécie les bonnes réponses. Je ne connaissais pas PIVOT avant. –

0

En supposant que la liste des Demo_Group à restituer est connue à l'avance, vous pouvez effectuer les opérations suivantes:

SELECT P.LAST_NAME, P.FIRST_NAME 
    , Sum(Case When Demo_Group = 'Male' Then 1 Else 0 End) As Male 
    , Sum(Case When Demo_Group = 'Female' Then 1 Else 0 End) As Female 
    , Sum(Case When Demo_Group = 'Teacher' Then 1 Else 0 End) As Teacher 
    , Sum(Case When Demo_Group = 'Alien' Then 1 Else 0 End) As Alien 
FROM PERSON P 
    JOIN PERSON_DEMOGRAPHIC PD 
     ON PD.PERSON_ID = P.PERSON_ID 
    JOIN DEMOGRAPHIC D 
     ON D.DEMOGRAPHIC_ID = PD.DEMOGRAPHIC_ID 
Group By P.LAST_NAME, P.FIRST_NAME 

Si la liste des valeurs Demo_Group ne sait pas, ce qui signifie que vous voulez que les colonnes à générées dynamiquement , alors la seule façon de le faire est d'utiliser un SQL dynamique. Ce n'est pas ce que SQL a été conçu pour faire et devrait plutôt être fait dans un outil de niveau intermédiaire ou de reporting.

Questions connexes