Oi! Seja bem-vindo!
Hoje veremos como TRANSFORMAR LINHAS em COLUNAS no SQL Server usando o PIVOT, esse comando simples que te ajudará a criar relatórios e gráficos fantásticos em um passe de mágica!
Em minha experiência esse tipo de conhecimento é vital para a sua carreira, porque demonstrar informações complexas de forma simples, para que gestores possam facilmente decidir a respeito, é uma habilidade que dá muito dinheiro e destaque profissional.
O que é PIVOT?
O comando PIVOT simplifica enormemente o trabalho de converter linhas de um resultado em colunas.
Muitas vezes quando apresento esse recurso sou questionado: “Mas para que vou querer fazer isso?”.
Em meu ponto de vista a maior utilização é quando você quer criar relatórios sintéticos ou organizar dados para uma apresentação. Veja no exemplo que mostrei no vídeo, no resultset abaixo, a visualização das informações é precária para dizer o mínimo. Colocar isso em um powerpoint é simplesmente inviável:
Ano | Colaborador | Valor |
---|---|---|
2013 | Abismail do Rosário | 2271700.00 |
2013 | Chaves Rosembaum | 2251600.00 |
2013 | Francisco Sanguessuga | 2052300.00 |
2013 | Josemar Pinto Godinho | 2226500.00 |
2013 | Navegador da Luz | 1858000.00 |
2013 | Necrotério Silveira | 2251500.00 |
2013 | Rolando da Rocha | 2422100.00 |
2014 | Abismail do Rosário | 2263700.00 |
2014 | Chaves Rosembaum | 2129200.00 |
2014 | Francisco Sanguessuga | 2521500.00 |
2014 | Josemar Pinto Godinho | 2239900.00 |
2014 | Navegador da Luz | 2197400.00 |
2014 | Necrotério Silveira | 2399100.00 |
2014 | Rolando da Rocha | 2164300.00 |
2015 | Abismail do Rosário | 2044400.00 |
2015 | Chaves Rosembaum | 2386200.00 |
2015 | Francisco Sanguessuga | 2600800.00 |
2015 | Josemar Pinto Godinho | 2096500.00 |
2015 | Navegador da Luz | 2341900.00 |
2015 | Necrotério Silveira | 2308600.00 |
2015 | Rolando da Rocha | 2121100.00 |
2016 | Abismail do Rosário | 2285200.00 |
2016 | Chaves Rosembaum | 2390200.00 |
2016 | Francisco Sanguessuga | 2212900.00 |
2016 | Josemar Pinto Godinho | 2152300.00 |
2016 | Navegador da Luz | 1907800.00 |
2016 | Necrotério Silveira | 2630400.00 |
2016 | Rolando da Rocha | 1840900.00 |
2017 | Abismail do Rosário | 2474300.00 |
2017 | Chaves Rosembaum | 2243200.00 |
2017 | Francisco Sanguessuga | 2263900.00 |
2017 | Josemar Pinto Godinho | 2445400.00 |
2017 | Navegador da Luz | 2152100.00 |
2017 | Necrotério Silveira | 2358500.00 |
2017 | Rolando da Rocha | 2287600.00 |
2018 | Abismail do Rosário | 33500.00 |
2018 | Chaves Rosembaum | 71500.00 |
2018 | Francisco Sanguessuga | 43200.00 |
2018 | Josemar Pinto Godinho | 85300.00 |
2018 | Navegador da Luz | 74300.00 |
2018 | Necrotério Silveira | 59400.00 |
2018 | Rolando da Rocha | 65800.00 |
Agora se gruparmos os resultados de venda dos anos em colunas, então temos algo muito interessante, fácil de explicar e incluir rapidamente em uma apresentação:
Colaborador | 2013 | 2014 | 2015 | 2016 | 2017 | 2018 |
---|---|---|---|---|---|---|
Abismail do Rosário | 2271700.00 | 2263700.00 | 2044400.00 | 2285200.00 | 2474300.00 | 33500.00 |
Chaves Rosembaum | 2251600.00 | 2129200.00 | 2386200.00 | 2390200.00 | 2243200.00 | 71500.00 |
Francisco Sanguessuga | 2052300.00 | 2521500.00 | 2600800.00 | 2212900.00 | 2263900.00 | 43200.00 |
Josemar Pinto Godinho | 2226500.00 | 2239900.00 | 2096500.00 | 2152300.00 | 2445400.00 | 85300.00 |
Navegador da Luz | 1858000.00 | 2197400.00 | 2341900.00 | 1907800.00 | 2152100.00 | 74300.00 |
Necrotério Silveira | 2251500.00 | 2399100.00 | 2308600.00 | 2630400.00 | 2358500.00 | 59400.00 |
Rolando da Rocha | 2422100.00 | 2164300.00 | 2121100.00 | 1840900.00 | 2287600.00 | 65800.00 |
Naturalmente, para fazer um gráfico também fica muito mais fácil usando um resultset como esse.
Como transformar Linhas em Colunas no SQL Server
Abaixo o script que utilizei no vídeo:
------------------------------------------------------------------ -- PIVOT: Transposição (linhas para colunas) ------------------------------------------------------------------ -------------------------------------------------- -- Banco de dados para nosso teste -------------------------------------------------- -- Banco de testes use master if db_id('curso') is not null drop database curso go create database curso go use curso go create table colaboradores ( id smallint identity(1,1) primary key, nm varchar(100) not null, ) insert into colaboradores values ('Abismail do Rosário'), ('Josemar Pinto Godinho'), ('Francisco Sanguessuga'), ('Rolando da Rocha'), ('Chaves Rosembaum'), ('Necrotério Silveira'), ('Navegador da Luz') create table produtos ( id smallint identity(1,1) primary key, nm varchar(100), vl decimal(10,2), ic_ativo bit not null default (1) ) insert produtos (nm, vl) values ('Mouse Gammer 25 botões', 200), ('Teclado Gammer 350 teclas', 300), ('Monitor 32 Pol Full HD', 1000), ('RAM DDR4 4GB Powerturbo', 500), ('CPU Nasa 10Ghz', 2000), ('HD SSD 1TB', 2000) create table vendas ( id int not null identity(1, 1) primary key, dt datetime not null, id_produto smallint not null foreign key references produtos(id), id_vendedor smallint foreign key references colaboradores(id), qt int check (qt > 0), vl_unitario decimal (10,2), vl_venda as qt * vl_unitario ) ;with cte_seq as ( select 1 as nr_cont union all select nr_cont + 1 from cte_seq where nr_cont < 10000) insert into vendas (dt, id_produto, id_vendedor, qt, vl_unitario) select dateadd(day, -(abs(checksum(newid())) % 1825), getdate()) dt, produto.id, colaborador.id, 1 + (abs(checksum(newid())) % 15) nr_quantidade, produto.vl vl_unitario from cte_seq left join (select top 1 id, vl from produtos order by newid()) produto on 1=1 left join (select top 1 id from colaboradores order by newid()) colaborador on 1=1 option (maxrecursion 0) go -------------------------------------------------- -- Transposição: de linhas para colunas -------------------------------------------------- -- Consulta padrão select year(dt) as Ano, c.nm as Colaborador, sum(vl_venda) as Valor from vendas join colaboradores c on c.id = vendas.id_vendedor group by c.nm, year(dt) -- PIVOT: Anos -> colunas: select * from ( select year(dt) as Ano, c.nm as Colaborador, sum(vl_venda) as Valor from vendas join colaboradores c on c.id = vendas.id_vendedor group by c.nm, year(dt) ) em_linha pivot (sum(valor) for ano in ([2012], [2013], [2014], [2015], [2016], [2017])) em_colunas order by 1 go -- PIVOT: Colaboradores -> colunas: select * from ( select year(dt) as Ano, c.nm as Colaborador, sum(vl_venda) as Valor from vendas join colaboradores c on c.id = vendas.id_vendedor group by c.nm, year(dt) ) em_linha pivot (sum(valor) for colaborador in ([Abismail do Rosário], [Chaves Rosembaum], [Francisco Sanguessuga])) em_colunas order by 1 go -------------------------------------------------- -- Excluindo dados de teste -------------------------------------------------- use master drop database curso <span data-mce-type="bookmark" style="display: inline-block; width: 0px; overflow: hidden; line-height: 0;" class="mce_SELRES_start"></span>
CONCLUSÃO
Como você viu, converter linhas para colunas é muito, mas muito fácil. As vezes fico empolgado com esse assunto pois sou do tempo que não existia o PIVOT… nem queira saber a trabalheira que dava fazer esse tipo de coisa.
Fico feliz que o SQL segue melhorando, e cada dia mais nós DBAs podemos trabalhar no que importa para o negócio ao invés de perder horas e horas com trabalho braçal
Espero que tenha gostado do artigo, nos vemos no próximo!
Abraço do seu amigo Josué 🙂
Bom dia! Obrigada por compartilhar isso conosco. Eu usei o pivot em um dos meus relatórios, porém, estou com dificuldade para trazer as informações em uma linha só. Ele está trazendo um bloco para cada mês, não estou conseguindo trazer apenas um bloco para todos.
Oi Elayne, entendo ser o o comportamento esperado, a não ser que agregue os valores de todos os meses com alguma função como “sum”. Abs Josué
Parabéns pela postagem, bem explicado.
Agora gostaria de saber se existe a possibilidade que realizar um Pivot Dinâmico dentro de uma View?
Oi Antônio, obrigado pelo seu feedback, fico feliz que tenha gostado! Seria ótimo encapsularmos esse código em um objeto usável em SELECTs (views ou funções)… porém views aceitam apenas um comando por objeto, e funções não permitem “side-effect operators”, como o comando “execute”.
Ou seja, para resolver esse tipo de caso, você precisará de uma Stored Procedure ou uma CLR.
Abraço, Josué