FROM – usando PIVOT e UNPIVOT
Aplica-se a: SQL Server Banco de Dados SQL do Azure Instância Gerenciada de SQL do Azure Azure Synapse Analytics PDW (Analytics Platform System) Ponto de extremidade de análise do SQL Warehouse no Microsoft Fabric
Você pode usar os operadores relacionais PIVOT
e UNPIVOT
para alterar uma expressão com valor de tabela para outra tabela. PIVOT
gira uma expressão com valor de tabela ao transformar os valores exclusivos de uma coluna na expressão em várias colunas na saída. PIVOT
também executa agregações onde elas são necessárias em quaisquer valores de coluna restantes desejados na saída final. UNPIVOT
executa a operação oposta a PIVOT
, girando colunas de uma expressão com valor de tabela em valores de coluna.
A sintaxe para PIVOT
é mais fácil e legível do que a sintaxe que poderia ser especificada em uma série complexa de SELECT...CASE
instruções. Para obter uma descrição completa da sintaxe de PIVOT
, consulte a cláusula FROM.
Observação
O uso repetido de em uma única instrução T-SQL pode afetar negativamente o desempenho da PIVOT
/UNPIVOT
consulta.
Os exemplos de código do Transact-SQL deste artigo usa o banco de dados de exemplo AdventureWorks2022
ou AdventureWorksDW2022
, que pode ser baixado da home page Microsoft SQL Server Samples and Community Projects.
Sintaxe
Esta seção resume como usar o PIVOT
operador and UNPIVOT
.
Sintaxe para o PIVOT
operador.
SELECT [ <non-pivoted column> [ AS <column name> ] , ]
...
[ <first pivoted column> [ AS <column name> ] ,
[ <second pivoted column> [ AS <column name> ] , ]
...
[ <last pivoted column> [ AS <column name> ] ] ]
FROM
( <SELECT query that produces the data> )
AS <alias for the source query>
PIVOT
(
<aggregation function> ( <column being aggregated> )
FOR <column that contains the values that become column headers>
IN ( <first pivoted column>
, <second pivoted column>
, ... <last pivoted column> )
) AS <alias for the pivot table>
[ <optional ORDER BY clause> ]
[ ; ]
Sintaxe para o UNPIVOT
operador.
SELECT [ <non-pivoted column> [ AS <column name> ] , ]
...
[ <output column for names of the pivot columns> [ AS <column name> ] , ]
[ <new output column created for values in result of the source query> [ AS <column name> ] ]
FROM
( <SELECT query that produces the data> )
AS <alias for the source query>
UNPIVOT
(
<new output column created for values in result of the source query>
FOR <output column for names of the pivot columns>
IN ( <first pivoted column>
, <second pivoted column>
, ... <last pivoted column> )
)
[ <optional ORDER BY clause> ]
[ ; ]
Comentários
Os identificadores de coluna na cláusula UNPIVOT
seguem a ordenação de catálogo.
Para o Banco de Dados SQL do Azure, a ordenação é sempre
SQL_Latin1_General_CP1_CI_AS
.Para bancos de dados parcialmente independentes do SQL Server, a ordenação é sempre
Latin1_General_100_CI_AS_KS_WS_SC
.
Se a coluna for combinada com outras colunas, uma cláusula COLLATE (COLLATE DATABASE_DEFAULT
) será necessária para evitar conflitos.
Nos pools do Microsoft Fabric e do Azure Synapse Analytics, as consultas com PIVOT
o operador falharão se houver uma GROUP BY
saída na coluna não dinâmica por PIVOT
. Como solução alternativa, remova a coluna não dinâmica do GROUP BY
. Os resultados da consulta são os mesmos, pois essa GROUP BY
cláusula é uma duplicata.
Exemplo de PIVOT básico
O seguinte exemplo de código produz uma tabela de duas colunas que tem quatro linhas.
USE AdventureWorks2022;
GO
SELECT DaysToManufacture, AVG(StandardCost) AS AverageCost
FROM Production.Product
GROUP BY DaysToManufacture;
Veja a seguir o conjunto de resultados.
DaysToManufacture AverageCost
------------------ ------------
0 5.0885
1 223.88
2 359.1082
4 949.4105
Nenhum produto é definido com um valor de 3
para DaysToManufacture
.
O código a seguir exibe o mesmo resultado, dinamizado de forma que os valores DaysToManufacture
tornem-se títulos de coluna. Uma coluna é fornecida por três ([3]
) dias, mesmo que os resultados sejam NULL
.
-- Pivot table with one row and five columns
SELECT 'AverageCost' AS CostSortedByProductionDays,
[0], [1], [2], [3], [4]
FROM (
SELECT DaysToManufacture,
StandardCost
FROM Production.Product
) AS SourceTable
PIVOT (
AVG(StandardCost) FOR DaysToManufacture IN
([0], [1], [2], [3], [4])
) AS PivotTable;
Veja a seguir o conjunto de resultados.
CostSortedByProductionDays 0 1 2 3 4
--------------------------- ----------- ----------- ----------- ----------- -----------
AverageCost 5.0885 223.88 359.1082 NULL 949.4105
Exemplo de PIVOT complexo
Um cenário comum em que PIVOT
pode ser útil ocorre quando você deseja gerar relatórios de tabulação cruzada para fornecer um resumo dos dados. Por exemplo, suponha que você deseje consultar a tabela PurchaseOrderHeader
no banco de dados de exemplo AdventureWorks2022
para determinar o número de ordens de compra colocadas por alguns funcionários. A consulta a seguir fornece esse relatório, ordenado por fornecedor.
USE AdventureWorks2022;
GO
SELECT VendorID,
[250] AS Emp1,
[251] AS Emp2,
[256] AS Emp3,
[257] AS Emp4,
[260] AS Emp5
FROM
(
SELECT PurchaseOrderID,
EmployeeID, VendorID
FROM Purchasing.PurchaseOrderHeader
) p
PIVOT
(
COUNT (PurchaseOrderID)
FOR EmployeeID IN ([250], [251], [256], [257], [260])
) AS pvt
ORDER BY pvt.VendorID;
Este é um conjunto de resultados parcial.
VendorID Emp1 Emp2 Emp3 Emp4 Emp5
----------- ----------- ----------- ----------- ----------- -----------
1492 2 5 4 4 4
1494 2 5 4 5 4
1496 2 4 4 5 5
1498 2 5 4 4 4
1500 3 4 4 5 4
Os resultados retornados por essa instrução subselecionar são dinamizados na coluna EmployeeID
.
SELECT PurchaseOrderID,
EmployeeID,
VendorID
FROM PurchaseOrderHeader;
Os valores exclusivos retornados pela coluna EmployeeID
tornam-se campos no conjunto de resultados final. Dessa forma, há uma coluna para cada EmployeeID
número especificado na cláusula dinâmica, que são funcionários 250
, 251
, 256
, 257
e 260
neste exemplo. A coluna PurchaseOrderID
serve como a coluna de valor, contra a qual as colunas retornadas na saída final, que são chamadas de colunas de agrupamento, são agrupadas. Neste caso, as colunas de agrupamento são agregadas pela função COUNT
. É exibida uma mensagem de aviso que indica que todos os PurchaseOrderID
valores nulos que aparecem na coluna não foram considerados ao calcular o COUNT
para cada funcionário.
Importante
Quando as funções de agregação são usadas com PIVOT
, a presença de quaisquer valores nulos na coluna de valor não é considerada ao calcular uma agregação.
Exemplo de UNPIVOT
UNPIVOT
executa praticamente a operação inversa de PIVOT
, transformando colunas em linhas. Suponha que a tabela produzida no exemplo anterior seja armazenada no banco de dados como pvt
e que você deseje girar os identificadores de coluna Emp1
, Emp2
, Emp3
, Emp4
e Emp5
em valores de linhas que correspondam a um fornecedor específico. Dessa forma, você deve identificar duas colunas extras.
A coluna que contém os valores de coluna que você está girando (Emp1
, Emp2
, e assim por diante) é chamada Employee
de , e a coluna que contém os valores que existem atualmente nas colunas que estão sendo giradas é chamada Orders
de . Essas colunas correspondem a pivot_column e value_column, respectivamente, na definição de Transact-SQL. Aqui está a consulta.
-- Create the table and insert values as portrayed in the previous example.
CREATE TABLE pvt (
VendorID INT,
Emp1 INT,
Emp2 INT,
Emp3 INT,
Emp4 INT,
Emp5 INT);
GO
INSERT INTO pvt
VALUES (1, 4, 3, 5, 4, 4);
INSERT INTO pvt
VALUES (2, 4, 1, 5, 5, 5);
INSERT INTO pvt
VALUES (3, 4, 3, 5, 4, 4);
INSERT INTO pvt
VALUES (4, 4, 2, 5, 5, 4);
INSERT INTO pvt
VALUES (5, 5, 1, 5, 5, 5);
GO
-- Unpivot the table.
SELECT VendorID, Employee, Orders
FROM (
SELECT VendorID, Emp1, Emp2, Emp3, Emp4, Emp5
FROM pvt
) p
UNPIVOT
(
Orders FOR Employee IN (Emp1, Emp2, Emp3, Emp4, Emp5)
) AS unpvt;
GO
Este é um conjunto de resultados parcial.
VendorID Employee Orders
----------- ----------- ------
1 Emp1 4
1 Emp2 3
1 Emp3 5
1 Emp4 4
1 Emp5 4
2 Emp1 4
2 Emp2 1
2 Emp3 5
2 Emp4 5
2 Emp5 5
UNPIVOT
não é exatamente o inverso de PIVOT
. PIVOT
executa uma agregação e mescla possíveis linhas múltiplas em uma única linha na saída. UNPIVOT
não reproduz o resultado da expressão com valor de tabela original, pois as linhas foram mescladas. Além disso, NULL
os valores na entrada de UNPIVOT
desaparecem na saída. Quando os valores desaparecem, isso mostra que pode ter havido valores originais NULL
na entrada antes da PIVOT
operação.
A exibição Sales.vSalesPersonSalesByFiscalYears
no banco de dados de exemplo AdventureWorks2022
usa PIVOT
para retornar o total de vendas de cada vendedor, para cada ano fiscal. Para gerar um script da exibição no SQL Server Management Studio, no Pesquisador de Objetos, localize a exibição na pasta Exibições do banco de dados AdventureWorks2022
. Clique com o botão direito do mouse no nome da exibição e selecione Gerar Script da Exibição como.