Il existe plusieurs façons de transformer ces données. Dans votre message initial, vous avez déclaré que PIVOT
semble trop complexe pour ce scénario, mais elle peut être appliquée très facilement en utilisant à la fois la fonction UNPIVOT
y PIVOT
dans SQL Server.
Toutefois, si vous n'avez pas accès à ces fonctions, il est possible de les reproduire en utilisant les éléments suivants UNION ALL
a UNPIVOT
et ensuite une fonction agrégée avec un CASE
déclaration à 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);
Union All, Aggregate et CASE Version :
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
Ver Bricolage SQL avec démo
El UNION ALL
effectue le UNPIVOT
des données en transformant les colonnes Paul, John, Tim, Eric
en rangs séparés. Ensuite, vous appliquez la fonction d'agrégation sum()
avec le case
pour obtenir les nouvelles colonnes pour chaque color
.
Version statique de Unpivot et Pivot :
Les deux UNPIVOT
y PIVOT
dans le serveur SQL rendent cette transformation beaucoup plus facile. Si vous connaissez toutes les valeurs que vous voulez 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
Ver Bricolage SQL avec démo
La requête interne avec le UNPIVOT
remplit la même fonction que le UNION ALL
. Il prend la liste des colonnes et la transforme en rangées, les PIVOT
effectue ensuite la transformation finale en colonnes.
Version Pivot Dynamique :
Si vous avez un nombre inconnu de colonnes ( Paul, John, Tim, Eric
dans votre exemple) et ensuite un nombre inconnu de couleurs à transformer, vous pouvez utiliser le sql dynamique pour générer la liste à UNPIVOT
et 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)
Ver Bricolage SQL avec démo
La version dynamique interroge à la fois yourtable
et ensuite le sys.columns
pour générer la liste des éléments à UNPIVOT
y PIVOT
. Elle est ensuite ajoutée à une chaîne de requête à exécuter. L'avantage de la version dynamique est que si vous avez une liste changeante de colors
et/ou names
cela 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 |