Det finns flera sätt att omvandla denna data. I ditt ursprungliga inlägg angav du att PIVOT
verkar för komplicerat för detta scenario, men det kan appliceras mycket enkelt med både UNPIVOT
och PIVOT
funktioner i SQL Server.
Men om du inte har tillgång till dessa funktioner kan detta replikeras med UNION ALL
till UNPIVOT
och sedan en aggregerad funktion med en CASE
uttalande till PIVOT
:
Skapa tabell:
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 och 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
utför UNPIVOT
av data genom att transformera kolumnerna Paul, John, Tim, Eric
i separata rader. Sedan tillämpar du aggregatfunktionen sum()
med case
för att få de nya kolumnerna för varje color
.
Unpivot och Pivot Static Version:
Både UNPIVOT
och PIVOT
funktioner i SQL server gör denna transformation mycket enklare. Om du känner till alla värden som du vill omvandla kan du hårdkoda dem till en statisk version för att 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 inre frågan med UNPIVOT
utför samma funktion som UNION ALL
. Den tar listan med kolumner och gör om den till rader, PIVOT
utför sedan den slutliga omvandlingen till kolumner.
Dynamisk pivotversion:
Om du har ett okänt antal kolumner (Paul, John, Tim, Eric
i ditt exempel) och sedan ett okänt antal färger att transformera kan du använda dynamisk sql för att generera listan till UNPIVOT
och sedan 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 dynamiska versionen frågar både yourtable
och sedan sys.columns
tabell för att generera listan över objekt till UNPIVOT
och PIVOT
. Detta läggs sedan till i en frågesträng som ska köras. Plusen med den dynamiska versionen är om du har en föränderlig lista med colors
och/eller names
detta genererar listan vid körning.
Alla tre frågorna ger samma resultat:
| NAME | RED | GREEN | BLUE |
-----------------------------
| Eric | 3 | 5 | 1 |
| John | 5 | 4 | 2 |
| Paul | 1 | 8 | 2 |
| Tim | 1 | 3 | 9 |