2009-11-03 8 views
1

J'ai vue SQL avec les données suivantes:SQL Tableau croisé dynamique

ID ClassName Description Flags 
1 Class1   Desc1  F1 
2 Class1   Desc1  F2 
3 Class1   Desc1  F3 
4 Class1   Desc1  F4 
5 Class2   Desc2  F2 
6 Class2   Desc2  F6 
7 Class3   Desc3  F1 
8 Class4   Desc4  F8 

Je veux entraîner quelque chose comme ceci:

ClassName Description F1 F2 F3 F4 F6 F8 
Class1   Desc1   T T T T F F 
Class2   Desc2   F T F F T F 
Class3   Desc3   T F F F F F 
Class4   Desc4   F F F F F T 

J'ai essayé de chercher des exemples de Pivot, mais tous sont soit pour SUM ou d'autres fonctions d'agrégat. Je ne sais pas si ça marchera comme je ne le fais pas non plus.

+0

Quelle version de SQL Server, et qu'avez-vous essayé? –

Répondre

0

select classname, description, cas lorsque des drapeaux = 'F1' alors fin 'T' else 'F' F1, cas où des drapeaux = 'F2' alors fin 'T' else 'F' F2, ...

0

Je crois que MS SQL Server supporte les tables pivots, mais je ne sais pas exactement comment les faire. Quand je dois faire pivoter des données dans MySQL, j'utilise Sum and Case. Cependant, cela ne fonctionne que lorsque vous savez à l'avance quels seront vos noms de colonne. Voici comment je pourrais le faire:

Select 
X.ClassName, 
X.Description, 
Case When X.F1 = 1 Then 'T' Else 'F' End As `F1`, 
Case When X.F2 = 1 Then 'T' Else 'F' End As `F2` 
/* etc. for the rest of your Flags*/ 
FROM (
    Select 
    ClassName, 
    Description, 
    Sum(Case When Flags = 'F1' Then 1 Else 0 End) As `F1`, 
    Sum(Case When Flags = 'F2' Then 1 Else 0 End) As `F2` 
    /* etc. for the rest of your Flags*/ 
    From 
    ClassTable 
    Group By 
    ClassTable.ClassName 
    ) X 

Dans le code ci-dessus, la sous-requête produira une sortie comme ce que vous voulez, sauf que vous aurez 1 et 0 (en supposant que vous ne le répétera jamais un drapeau pour une classe). La requête "principale" en haut de la déclaration transforme simplement les 1 et 0 en T et F. Encore une fois, cela nécessite que vous sachiez quels seront vos noms de colonnes, mais c'est la seule façon de le faire sans que "PIVOT" soit intégré au langage SQL que vous utilisez. MS SQL peut avoir un PIVOT intégré, donc vous pouvez vouloir creuser pour trouver cela.

+0

Je ne saurai pas quels sont mes drapeaux car l'utilisateur final a la possibilité d'ajouter, de mettre à jour ou de supprimer des drapeaux et de s'associer à n'importe quelle classe (par exemple, ajouter un nouveau drapeau F101 ou renommer F1 en F01). J'utilise SQL Express 2005 – Deepak

+0

Voici un hack méchant: Si vous avez la possibilité de générer SQL à l'exécution, vous pouvez interroger votre table pour tous les noms de drapeau disponibles, puis générer l'instruction SQL avec les colonnes (Sum (Case When Flags ...) généré automatiquement à partir du code, ce qui me rend mal à l'aise d'y penser, mais cela fonctionnerait si vous aviez du code avec lequel travailler. –

1

Henry Fao est sur la bonne voie - mais vous devez "aplatir" les rangées avec un groupe de.

 
select ClassName as ClassName, Description as Description 
    , coalesce(max(F1), 'F') as F1 
    , coalesce(max(F2), 'F') as F2 
    , etc 
from (
     select classname, description 
      , case when flags = 'F1' then 'T' else null end as F1 
      , case when flags = 'F2' then 'T' else null end as F2 
      etc. 
     from tbl 
     ) as t 
    group by ClassName, Description 

Il ne devrait y avoir qu'un 'T' dans la colonne F1 de chaque groupe. Les autres lignes auront une valeur nulle dans la colonne T1. La fonction max() ignore les valeurs nulles et retournera le 'T' - s'il y en a un.

0

Ce n'est pas joli et je n'aime généralement pas SQL créé dynamiquement, mais avec une liste inconnue de drapeaux, je ne sais pas vraiment comment vous le feriez autrement. De plus, vous avez raison de dire que la commande PIVOT attend un agrégat, alors j'ai juste utilisé MAX. Oui, c'est un peu hackish, mais cela fait le travail et évoluera au fur et à mesure que de nouveaux drapeaux seront ajoutés. Je pense que cela devrait fonctionner sur les versions 2005/2008 de SQL-SERVER. Je ne suis pas sûr de 2003 car je ne sais pas s'il a la commande XML PATH.

Declare @ColumnsIn varchar(max) 
Declare @ColumnsIsNull varchar(max) 
Declare @sql varchar(max) 

Select @ColumnsIn = Stuff((Select Distinct ',[' + Flags + ']' From Classes For XML PATH('')),1,1,'') 
Select @ColumnsIsNull = Stuff((Select Distinct ', IsNull([' + Flags + '], ''F'') as [' + Flags + ']' From Classes For XML PATH('')),1,1,'') 

Set @sql = ' 
    Select 
     ClassName, 
     Description, 
     ' + @ColumnsIsNull + ' 
    FROM 
    (
     Select 
      Classes.ClassName, 
      Classes.Description, 
      Classes.Flags, 
      ''T'' as HasFlag 
     From 
      Classes 
    ) as Sub1 
    Pivot (Max(HasFlag) For Flags in (' + @ColumnsIn + ')) as Sub2' 

Execute(@sql) 
Questions connexes