Il existe plusieurs manières de transformer ces données. Dans votre article d'origine, vous avez déclaré que cela PIVOTsemble trop complexe pour ce scénario, mais cela peut être appliqué très facilement à l'aide des fonctions UNPIVOTetPIVOT de SQL Server.
Cependant, si vous n'avez pas accès à ces fonctions, cela peut être répliqué à l'aide de UNION ALLto UNPIVOT, puis d'une fonction d'agrégation avec une CASEinstruction to PIVOT:
Créer une table:
CREATE TABLE yourTable([color] varchar(5), [Paul] int, [John] int, [Tim] int, [Eric] int);
INSERT INTO yourTable
([color], [Paul], [John], [Tim], [Eric])
VALUES
('Red', 1, 5, 1, 3),
('Green', 8, 4, 3, 5),
('Blue', 2, 2, 9, 1);
Version Union All, Agrégat et CASE:
select name,
sum(case when color = 'Red' then value else 0 end) Red,
sum(case when color = 'Green' then value else 0 end) Green,
sum(case when color = 'Blue' then value else 0 end) Blue
from
(
select color, Paul value, 'Paul' name
from yourTable
union all
select color, John value, 'John' name
from yourTable
union all
select color, Tim value, 'Tim' name
from yourTable
union all
select color, Eric value, 'Eric' name
from yourTable
) src
group by name
Voir SQL Fiddle avec démo
Le UNION ALLexécute la UNPIVOTdes données en transformant les colonnes Paul, John, Tim, Ericen lignes séparées. Ensuite, vous appliquez la fonction d'agrégation sum()avec l' caseinstruction pour obtenir les nouvelles colonnes pour chacun color.
Unpivot et la version statique du pivot:
Les fonctions UNPIVOTet PIVOTdu serveur SQL rendent cette transformation beaucoup plus facile. Si vous connaissez toutes les valeurs que vous souhaitez transformer, vous pouvez les coder en dur dans une version statique pour obtenir le résultat:
select name, [Red], [Green], [Blue]
from
(
select color, name, value
from yourtable
unpivot
(
value for name in (Paul, John, Tim, Eric)
) unpiv
) src
pivot
(
sum(value)
for color in ([Red], [Green], [Blue])
) piv
Voir SQL Fiddle avec démo
La requête interne avec le UNPIVOTexécute la même fonction que le UNION ALL. Il prend la liste des colonnes et la transforme en lignes, PIVOTpuis effectue la transformation finale en colonnes.
Version du pivot dynamique:
Si vous avez un nombre inconnu de colonnes ( Paul, John, Tim, Ericdans votre exemple), puis un nombre inconnu de couleurs à transformer, vous pouvez utiliser SQL dynamique pour générer la liste vers UNPIVOTet ensuite PIVOT:
DECLARE @colsUnpivot AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX),
@colsPivot as NVARCHAR(MAX)
select @colsUnpivot = stuff((select ','+quotename(C.name)
from sys.columns as C
where C.object_id = object_id('yourtable') and
C.name <> 'color'
for xml path('')), 1, 1, '')
select @colsPivot = STUFF((SELECT ','
+ quotename(color)
from yourtable t
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query
= 'select name, '+@colsPivot+'
from
(
select color, name, value
from yourtable
unpivot
(
value for name in ('+@colsUnpivot+')
) unpiv
) src
pivot
(
sum(value)
for color in ('+@colsPivot+')
) piv'
exec(@query)
Voir SQL Fiddle avec démo
La version dynamique interroge les deux yourtable, puis la sys.columnstable pour générer la liste des éléments vers UNPIVOTet PIVOT. Ceci est ensuite ajouté à une chaîne de requête à exécuter. Le plus de la version dynamique est si vous avez une liste changeante de colorset / ou namescela générera la liste au moment de l'exécution.
Les trois requêtes produiront le même résultat:
| NAME | RED | GREEN | BLUE |
-----------------------------
| Eric | 3 | 5 | 1 |
| John | 5 | 4 | 2 |
| Paul | 1 | 8 | 2 |
| Tim | 1 | 3 | 9 |