Esistono diversi modi per trasformare questi dati. Nel tuo post originale, hai dichiarato che PIVOT
sembra troppo complesso per questo scenario, ma può essere applicato molto facilmente usando sia il UNPIVOT
e PIVOT
funzioni in SQL Server.
Tuttavia, se non hai accesso a queste funzioni, queste possono essere replicate utilizzando UNION ALL
a UNPIVOT
e quindi una funzione aggregata con un CASE
dichiarazione in PIVOT
:
Crea tabella:
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 e 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
Vedi SQL Fiddle con demo
Il UNION ALL
esegue il UNPIVOT
dei dati trasformando le colonne Paul, John, Tim, Eric
in file separate. Quindi applichi la funzione di aggregazione sum()
con il case
istruzione per ottenere le nuove colonne per ogni color
.
Versione statica unpivot e pivot:
Sia il UNPIVOT
e PIVOT
le funzioni in SQL Server rendono questa trasformazione molto più semplice. Se conosci tutti i valori che desideri trasformare, puoi codificarli in una versione statica per ottenere il risultato:
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
Vedi SQL Fiddle con demo
La query interna con UNPIVOT
svolge la stessa funzione di UNION ALL
. Prende l'elenco delle colonne e lo trasforma in righe, il PIVOT
quindi esegue la trasformazione finale in colonne.
Versione pivot dinamica:
Se hai un numero sconosciuto di colonne (Paul, John, Tim, Eric
nel tuo esempio) e quindi un numero sconosciuto di colori da trasformare puoi utilizzare sql dinamico per generare l'elenco in UNPIVOT
e poi 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)
Vedi SQL Fiddle con demo
La versione dinamica interroga sia yourtable
e poi sys.columns
tabella per generare l'elenco degli elementi da UNPIVOT
e PIVOT
. Questo viene quindi aggiunto a una stringa di query da eseguire. Il vantaggio della versione dinamica è se hai un elenco mutevole di colors
e/o names
questo genererà l'elenco in fase di esecuzione.
Tutte e tre le query produrranno lo stesso risultato:
| NAME | RED | GREEN | BLUE |
-----------------------------
| Eric | 3 | 5 | 1 |
| John | 5 | 4 | 2 |
| Paul | 1 | 8 | 2 |
| Tim | 1 | 3 | 9 |