Er zijn verschillende manieren waarop u deze gegevens kunt transformeren. In je oorspronkelijke bericht verklaarde je dat PIVOT
lijkt te complex voor dit scenario, maar het kan heel gemakkelijk worden toegepast met zowel de UNPIVOT
en PIVOT
functies in SQL Server.
Als u echter geen toegang heeft tot deze functies, kan dit worden gerepliceerd met UNION ALL
naar UNPIVOT
en dan een aggregatiefunctie met een CASE
statement naar PIVOT
:
Tafel maken:
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 en CASE-versie:
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
Zie SQL Fiddle met demo
De UNION ALL
voert de UNPIVOT
. uit van de gegevens door de kolommen Paul, John, Tim, Eric
. te transformeren in aparte rijen. Dan pas je de aggregatiefunctie sum()
. toe met de case
statement om de nieuwe kolommen voor elke color
te krijgen .
Ongedaan maken van draaien en draaien van statische versie:
Zowel de UNPIVOT
en PIVOT
functies in de SQL-server maken deze transformatie veel gemakkelijker. Als u alle waarden kent die u wilt transformeren, kunt u ze hardcoderen in een statische versie om het resultaat te krijgen:
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
Zie SQL Fiddle met demo
De innerlijke vraag met de UNPIVOT
vervult dezelfde functie als de UNION ALL
. Het neemt de lijst met kolommen en verandert het in rijen, de PIVOT
voert vervolgens de laatste transformatie in kolommen uit.
Dynamische draaiversie:
Als u een onbekend aantal kolommen heeft (Paul, John, Tim, Eric
in uw voorbeeld) en vervolgens een onbekend aantal kleuren om te transformeren, kunt u dynamische sql gebruiken om de lijst te genereren naar UNPIVOT
en dan 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, '[email protected]+'
from
(
select color, name, value
from yourtable
unpivot
(
value for name in ('[email protected]+')
) unpiv
) src
pivot
(
sum(value)
for color in ('[email protected]+')
) piv'
exec(@query)
Zie SQL Fiddle met demo
De dynamische versie bevraagt zowel yourtable
en dan de sys.columns
tabel om de lijst met items te genereren voor UNPIVOT
en PIVOT
. Dit wordt vervolgens toegevoegd aan een uit te voeren queryreeks. Het voordeel van de dynamische versie is als je een wisselende lijst met colors
hebt en/of names
dit zal de lijst tijdens runtime genereren.
Alle drie de zoekopdrachten zullen hetzelfde resultaat opleveren:
| NAME | RED | GREEN | BLUE |
-----------------------------
| Eric | 3 | 5 | 1 |
| John | 5 | 4 | 2 |
| Paul | 1 | 8 | 2 |
| Tim | 1 | 3 | 9 |