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, 'example@sqldat.com+'
from
(
select color, name, value
from yourtable
unpivot
(
value for name in ('example@sqldat.com+')
) unpiv
) src
pivot
(
sum(value)
for color in ('example@sqldat.com+')
) 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 |