En utilisant cette table:
| CUST | PRODUCT | QTY | SMALLEST | ----------------------------------- | E | 1600 | 2 | 1 | | F | 1600 | 6 | 9 | | G | 1600 | 1 | 8 |
Je veux le faire pivoter pour qu'il ressemble à ceci:
| E | F | G | ------------------------------ | 1600 | 1600 | 1600 | | 2 | 6 | 1 | | 1 | 9 | 8 |
Je sais comment faire avec une rangée unique. Si je n'ai que QTY ou que j'ai le plus petit, cela fonctionne bien avec cette requête par exemple:
Question
SELECT E, F, G FROM ( SELECT CUST, PRODUCT, QTY FROM Product) up PIVOT (SUM(QTY) FOR CUST IN (E,F,G)) AS pvt
Sortie
| E | F | G | ------------- | 2 | 6 | 1 |
Mais, si j'ajoute une autre colonne à la concoction dans une autre requête, j'obtiens ce bordel:
Question
SELECT E, F, G FROM ( SELECT CUST, PRODUCT, QTY, SMALLEST FROM Product) up PIVOT (SUM(QTY) FOR CUST IN (E,F,G)) AS pvt
Sortie
| E | F | G | ---------------------------- | 2 | (null) | (null) | | (null) | (null) | 1 | | (null) | 6 | (null) |
Et c'est facile de voir pourquoi quand je change la requête:
Question
SELECT product,smallest, E, F, G FROM ( SELECT CUST, PRODUCT, QTY, SMALLEST FROM Product) up PIVOT (SUM(QTY) FOR CUST IN (E,F,G)) AS pvt
Sortie
| PRODUCT | SMALLEST | E | F | G | ------------------------------------------------- | 1600 | 1 | 2 | (null) | (null) | | 1600 | 8 | (null) | (null) | 1 | | 1600 | 9 | (null) | 6 | (null) |
Le motif devient évident. Il s'agit de find où il y a 1600 et 1 il y a une valeur E: 2, où il y a 1600 et 8 il y a une valeur F 6, etc.
J'ai le problème, mais je n'ai aucune idée de comment le réparer. Quelqu'un peut-il m'aider dans ma quête futile?
SQL Fiddle
Vraiment, vous voulez un UNPIVOT
pour prendre soin des multiples colonnes, puis un PIVOT
pour get vos données. Ma façon préférée de faire UNPIVOT
est d'utiliser CROSS APPLY
, mais vous pouvez le faire comme vous voulez. Comme tel.
SELECT E, F, G FROM ( SELECT CUST, ColumnName, Value FROM Product CROSS APPLY ( VALUES ('PRODUCT', PRODUCT), ('QTY', QTY), ('SMALLEST',SMALLEST)) UnPivoted(ColumnName, Value)) up PIVOT (SUM(VALUE) FOR CUST IN (E,F,G)) AS pvt
Et bien sûr, si vous voulez voir de quelle colonne proviennent les valeurs:
SELECT ColumnName, E, F, G FROM ( SELECT CUST, ColumnName, Value FROM Product CROSS APPLY ( VALUES ('PRODUCT', PRODUCT), ('QTY', QTY), ('SMALLEST',SMALLEST)) UnPivoted(ColumnName, Value)) up PIVOT (SUM(VALUE) FOR CUST IN (E,F,G)) AS pvt
MODIFIER:
Voici une solution pour plusieurs types. Fondamentalement, vous devez avoir plusieurs requêtes, une pour chaque type de données. Entre autres choses, vous avez un SUM
dans votre requête numérique qui ne fonctionnera pas sur les colonnes varchar. Votre sortie doit également être tous les mêmes. Cela signifie que vous devez convertir n'importe quelle colonne numérique ou date en varchar.
SELECT ColumnName, CAST(E AS varchar(30)) E, CAST(F AS varchar(30)) F, CAST(G AS varchar(30)) G FROM ( SELECT CUST, ColumnName, Value FROM Product CROSS APPLY ( VALUES ('PRODUCT', PRODUCT), ('QTY', QTY), ('SMALLEST',SMALLEST)) UnPivoted(ColumnName, Value)) up PIVOT (SUM(VALUE) FOR CUST IN (E,F,G)) AS pvt UNION ALL SELECT ColumnName, E, F, G FROM ( SELECT CUST, ColumnName, Value FROM Product CROSS APPLY ( VALUES ('CharColA', CharColA), ('CharColB', CharColB)) UnPivoted(ColumnName, Value)) up PIVOT (MIN(VALUE) FOR CUST IN (E,F,G)) AS pvt
Vous pouvez le faire avec CROSS-APPLY
et PIVOT
:
SELECT E,F,G FROM ( SELECT Cust,col,value FROM #Product CROSS APPLY ( VALUES ('E', Product),('F', QTY),('G', SMALLEST) ) C (COL, VALUE) ) SRC PIVOT ( MAX(VALUE) FOR CUST IN (E,F,G) ) PIV
Démo: SQL Fiddle