Existem várias maneiras de transformar esses dados. Em sua postagem original, você afirmou que PIVOT
parece muito complexo para este cenário, mas pode ser aplicado facilmente usando o UNPIVOT
ePIVOT
funções do SQL Server.
No entanto, se você não tiver acesso a essas funções, isso pode ser replicado usando UNION ALL
para UNPIVOT
e, em seguida, uma função agregada com uma CASE
instrução paraPIVOT
:
Criar a tabela:
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);
Versão de união de todos, agregado 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
Vejo SQL Fiddle com Demo
O UNION ALL
executa a eliminação UNPIVOT
dos dados transformando as colunas Paul, John, Tim, Eric
em linhas separadas. Em seguida, você aplica a função de agregação sum()
com a case
instrução para obter as novas colunas para cadacolor
.
Versão Estática Unpivot e Pivot:
As funções UNPIVOT
e PIVOT
no servidor SQL tornam essa transformação muito mais fácil. Se você conhece todos os valores que deseja transformar, pode codificá-los em uma versão estática para obter o resultado:
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
Vejo SQL Fiddle com Demo
A consulta interna com UNPIVOT
executa a mesma função que UNION ALL
. Ele pega a lista de colunas e a transforma em linhas, oPIVOT
então realiza a transformação final em colunas.
Versão dinâmica do pivô:
Se você tiver um número desconhecido de colunas ( Paul, John, Tim, Eric
em seu exemplo) e, em seguida, um número desconhecido de cores para transformar, você pode usar sql dinâmico para gerar a lista para UNPIVOT
e então 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)
Vejo SQL Fiddle com Demo
A versão dinâmica consulta ambos yourtable
e a sys.columns
tabela para gerar a lista de itens para UNPIVOT
e PIVOT
. Isso é então adicionado a uma string de consulta a ser executada. A vantagem da versão dinâmica é se você tem uma lista de alteração de colors
e / ou names
isso irá gerar a lista em tempo de execução.
Todas as três consultas produzirão o mesmo resultado:
| NAME | RED | GREEN | BLUE |
-----------------------------
| Eric | 3 | 5 | 1 |
| John | 5 | 4 | 2 |
| Paul | 1 | 8 | 2 |
| Tim | 1 | 3 | 9 |