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 muito facilmente usando o UNPIVOT
e PIVOT
funções no 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 um CASE
instrução para PIVOT
:Criar 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);
Union All, Agregado e Versão 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
Veja SQL Fiddle com demonstração
O
UNION ALL
executa o UNPIVOT
dos dados transformando as colunas Paul, John, Tim, Eric
em linhas separadas. Então você aplica a função agregada sum()
com o case
instrução para obter as novas colunas para cada color
. Unpivot e Pivot versão estática:
Tanto o
UNPIVOT
e PIVOT
funções no SQL Server 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
Veja SQL Fiddle com demonstração
A consulta interna com o
UNPIVOT
executa a mesma função que UNION ALL
. Ele pega a lista de colunas e a transforma em linhas, o PIVOT
em seguida, realiza a transformação final em colunas. Versão dinâmica dinâmica:
Se você tiver um número desconhecido de colunas (
Paul, John, Tim, Eric
no seu exemplo) e, em seguida, um número desconhecido de cores para transformar, você pode usar o 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, '[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)
Veja SQL Fiddle com demonstração
A versão dinâmica consulta tanto
yourtable
e, em seguida, o 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ê tiver uma lista de colors
em mudança 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 |