Esistono diversi modi per trasformare questi dati. Nel tuo post originale, hai affermato che PIVOT
sembra troppo complesso per questo scenario, ma può essere applicato molto facilmente utilizzando sia il UNPIVOT
chePIVOT
funzioni in SQL Server.
Tuttavia, se non si ha accesso a tali funzioni, è possibile replicarlo utilizzando UNION ALL
a UNPIVOT
e quindi una funzione di aggregazione con CASE
un'istruzione a 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);
Versione Union All, Aggregate e 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
Vedi SQL Fiddle con Demo
Il UNION ALL
esegue il UNPIVOT
dei dati trasformando le colonne Paul, John, Tim, Eric
in righe separate. Quindi si applica la funzione di aggregazione sum()
con l' case
istruzione per ottenere le nuove colonne per ciascuna color
.
Versione statica unpivot e pivot:
Sia l' UNPIVOT
e PIVOT
funzioni in SQL Server rendono questa trasformazione molto più facile. Se conosci tutti i valori che vuoi trasformare, puoi codificarli come hardcoded 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
esegue la stessa funzione di UNION ALL
. Prende l'elenco delle colonne e lo trasforma in righe, 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 UNPIVOT
e quindi 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, '+@colsPivot+'
from
(
select color, name, value
from yourtable
unpivot
(
value for name in ('+@colsUnpivot+')
) unpiv
) src
pivot
(
sum(value)
for color in ('+@colsPivot+')
) piv'
exec(@query)
Vedi SQL Fiddle con Demo
La versione dinamica interroga entrambi yourtable
e quindi la sys.columns
tabella per generare l'elenco di elementi in UNPIVOT
e PIVOT
. Questo viene quindi aggiunto a una stringa di query da eseguire. Il vantaggio della versione dinamica è se si dispone di un elenco di modifiche 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 |