Existuje několik způsobů, jak můžete tato data transformovat. Ve svém původním příspěvku jste uvedli, že PIVOT
se zdá být pro tento scénář příliš složitý, ale lze jej velmi snadno použít pomocí obou UNPIVOT
a PIVOT
funkce na serveru SQL Server.
Pokud však k těmto funkcím nemáte přístup, lze je replikovat pomocí UNION ALL
UNPIVOT
a poté agregační funkce s CASE
příkaz PIVOT
:
Vytvořit tabulku:
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 and 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
Viz SQL Fiddle with Demo
UNION ALL
provede UNPIVOT
dat transformací sloupců Paul, John, Tim, Eric
do samostatných řad. Poté použijete agregační funkci sum()
s case
pro získání nových sloupců pro každou color
.
Uvolnění a otočení statické verze:
Oba UNPIVOT
a PIVOT
funkce na SQL serveru tuto transformaci značně usnadňují. Pokud znáte všechny hodnoty, které chcete transformovat, můžete je napevno zakódovat do statické verze a získat výsledek:
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
Viz SQL Fiddle with Demo
Vnitřní dotaz s UNPIVOT
provádí stejnou funkci jako UNION ALL
. Vezme seznam sloupců a změní jej na řádky, PIVOT
poté provede konečnou transformaci do sloupců.
Verze dynamického pivotu:
Pokud máte neznámý počet sloupců (Paul, John, Tim, Eric
ve vašem příkladu) a poté neznámý počet barev k transformaci, můžete pomocí dynamického sql vygenerovat seznam a UNPIVOT
a poté 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)
Viz SQL Fiddle with Demo
Dynamická verze se dotazuje jak yourtable
a poté sys.columns
tabulky pro vygenerování seznamu položek k UNPIVOT
a PIVOT
. To se pak přidá do řetězce dotazu, který se má provést. Výhodou dynamické verze je, že máte měnící se seznam colors
a/nebo names
toto vygeneruje seznam za běhu.
Všechny tři dotazy přinesou stejný výsledek:
| NAME | RED | GREEN | BLUE |
-----------------------------
| Eric | 3 | 5 | 1 |
| John | 5 | 4 | 2 |
| Paul | 1 | 8 | 2 |
| Tim | 1 | 3 | 9 |