Istnieje kilka sposobów przekształcania tych danych. W oryginalnym poście stwierdziłeś, że PIVOT
wydaje się zbyt skomplikowany dla tego scenariusza, ale można go bardzo łatwo zastosować za pomocą zarówno UNPIVOT
i PIVOT
funkcje w SQL Server.
Jeśli jednak nie masz dostępu do tych funkcji, można je zreplikować za pomocą UNION ALL
do UNPIVOT
a następnie funkcję agregującą z CASE
oświadczenie do PIVOT
:
Utwórz 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);
Wersja Union All, Aggregate i CASE:
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
Zobacz SQL Fiddle z demonstracją
UNION ALL
wykonuje UNPIVOT
danych poprzez przekształcenie kolumn Paul, John, Tim, Eric
w osobne rzędy. Następnie stosujesz funkcję agregującą sum()
z case
oświadczenie, aby uzyskać nowe kolumny dla każdego color
.
Wersje statyczne Unpivot i Pivot:
Zarówno UNPIVOT
i PIVOT
funkcje w serwerze SQL znacznie ułatwiają tę transformację. Jeśli znasz wszystkie wartości, które chcesz przekształcić, możesz je na stałe zakodować w wersji statycznej, aby uzyskać wynik:
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
Zobacz SQL Fiddle z demonstracją
Zapytanie wewnętrzne z UNPIVOT
wykonuje tę samą funkcję co UNION ALL
. Pobiera listę kolumn i zamienia ją w wiersze, PIVOT
następnie wykonuje ostateczną transformację w kolumny.
Dynamiczna wersja obrotowa:
Jeśli masz nieznaną liczbę kolumn (Paul, John, Tim, Eric
w twoim przykładzie), a następnie nieznaną liczbę kolorów do przekształcenia, możesz użyć dynamicznego sql, aby wygenerować listę do UNPIVOT
a następnie 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)
Zobacz SQL Fiddle z demonstracją
Wersja dynamiczna wysyła zapytania zarówno do yourtable
a następnie sys.columns
tabela do generowania listy elementów do UNPIVOT
i PIVOT
. Jest to następnie dodawane do ciągu zapytania do wykonania. Plusem wersji dynamicznej jest to, że masz zmieniającą się listę colors
i/lub names
to wygeneruje listę w czasie wykonywania.
Wszystkie trzy zapytania dadzą ten sam wynik:
| NAME | RED | GREEN | BLUE |
-----------------------------
| Eric | 3 | 5 | 1 |
| John | 5 | 4 | 2 |
| Paul | 1 | 8 | 2 |
| Tim | 1 | 3 | 9 |