Der er flere måder, hvorpå du kan transformere disse data. I dit oprindelige indlæg angav du at PIVOT
virker for komplekst til dette scenarie, men det kan anvendes meget nemt ved at bruge både UNPIVOT
og PIVOT
funktioner i SQL Server.
Men hvis du ikke har adgang til disse funktioner, kan dette replikeres ved hjælp af UNION ALL
til UNPIVOT
og derefter en aggregeret funktion med en CASE
sætning til PIVOT
:
Opret tabel:
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 og 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
Se SQL Fiddle with Demo
UNION ALL
udfører UNPIVOT
af dataene ved at transformere kolonnerne Paul, John, Tim, Eric
i separate rækker. Derefter anvender du den samlede funktion sum()
med case
sætning for at få de nye kolonner for hver color
.
Unpivot og Pivot Static Version:
Både UNPIVOT
og PIVOT
funktioner i SQL server gør denne transformation meget lettere. Hvis du kender alle de værdier, du vil transformere, kan du hardkode dem til en statisk version for at få resultatet:
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
Se SQL Fiddle with Demo
Den indre forespørgsel med UNPIVOT
udfører den samme funktion som UNION ALL
. Den tager listen over kolonner og omdanner den til rækker, PIVOT
udfører derefter den endelige transformation til kolonner.
Dynamisk pivotversion:
Hvis du har et ukendt antal kolonner (Paul, John, Tim, Eric
i dit eksempel) og derefter et ukendt antal farver, der skal transformeres, kan du bruge dynamisk sql til at generere listen til UNPIVOT
og derefter 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)
Se SQL Fiddle with Demo
Den dynamiske version forespørger både yourtable
og derefter sys.columns
tabel for at generere listen over elementer til UNPIVOT
og PIVOT
. Dette føjes derefter til en forespørgselsstreng, der skal udføres. Fordelen ved den dynamiske version er, hvis du har en skiftende liste over colors
og/eller names
dette vil generere listen ved kørsel.
Alle tre forespørgsler vil give det samme resultat:
| NAME | RED | GREEN | BLUE |
-----------------------------
| Eric | 3 | 5 | 1 |
| John | 5 | 4 | 2 |
| Paul | 1 | 8 | 2 |
| Tim | 1 | 3 | 9 |