Applies to: SQL Server (all supported versions) Azure SQL database Azure SQL managed instance Azure Synapse Analytics parallel data warehouse
You can use the PIVOT
and UNPIVOT
relational operator to change a table-valued expression to another table. PIVOT
Rotate table-valued expressions by converting the unique value of one column in the expression to multiple columns in the output. PIVOT
Run aggregation when you need to perform aggregation on all remaining column values needed for the final output. Contrary to what PIVOT does, UNPIVOT
it rotates the columns of a table-valued expression to column values.
PIVOT
The provided SELECT...CASE
syntax is simpler and more readable than the syntax specified in a series of complex statements. For PIVOT
a complete description of the syntax, see FROM (Transact-SQL) .
grammar
The following syntax summarizes how to use PIVOT
operators.
copy
SELECT <non-pivoted column>,
[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 will become column headers>]
IN ( [first pivoted column], [second pivoted column],
... [last pivoted column])
) AS <alias for the pivot table>
<optional ORDER BY clause>;
Remarks
UNPIVOT
The column identifier in the clause must follow the catalog ordering rules. For SQL databases, the collation is always SQL_Latin1_General_CP1_CI_AS
. For databases partly included in SQL Server, the collation is always Latin1_General_100_CI_AS_KS_WS_SC
. If you merge this column with other columns, you need the collate clause ( COLLATE DATABASE_DEFAULT
) to avoid conflicts.
Simple PIVOT example
The following code example generates a table with two columns and four rows.
SQL replication
USE AdventureWorks2014 ;
GO
SELECT DaysToManufacture, AVG(StandardCost) AS AverageCost
FROM Production.Product
GROUP BY DaysToManufacture;
Here is the result set:
copy
DaysToManufacture AverageCost
----------------- -----------
0 5.0885
1 223.88
2 359.1082
4 949.4105
There is no DaysToManufacture
product defined as 3.
The following code shows the same result, which is pivoted so that the DaysToManufacture
values become column headings. Providing a column represents San [3]
days, even if the result is NULL
.
SQL replication
-- Pivot table with one row and five columns
SELECT 'AverageCost' AS Cost_Sorted_By_Production_Days,
[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;
Here is the result set:
copy
Cost_Sorted_By_Production_Days 0 1 2 3 4
------------------------------ ----------- ----------- ----------- ----------- -----------
AverageCost 5.0885 223.88 359.1082 NULL 949.4105
Complex PIVOT example
If you want to generate a cross-tab report to summarize data, you may often find PIVOT
it useful. For example, suppose you need PurchaseOrderHeader
to query a AdventureWorks2014
table in a sample database to determine the number of purchase orders placed by certain employees. The following query provides this report (sorted by vendor).
SQL replication
USE AdventureWorks2014;
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;
The following is a partial result set.
copy
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
EmployeeID
The results returned by this nested select statement will be pivoted on the columns.
SQL replication
SELECT PurchaseOrderID, EmployeeID, VendorID
FROM PurchaseOrderHeader;
EmployeeID
The unique value returned by the column becomes a field in the final result set. Accordingly, each pivot specified in clause EmployeeID
numbers are columns: In this example, for employees 250
, 251
, 256
, 257
and 260
. PurchaseOrderID
The column is used as the value column, and the columns returned in the final output (called grouping columns) will be grouped according to this column. In this example, the COUNT
grouping columns are aggregated by function. Note that the system displays a warning message to indicate that any NULL values in the column were COUNT
not considered when calculating for each employee PurchaseOrderID
.
important
If the aggregation function is PIVOT
used with, any null values that appear in the value column will not be considered when calculating the aggregation.
Example of inverse perspective
It PIVOT
is almost the opposite of the operation performed, UNPIVOT
rotating the columns to rows. Suppose in the example above is generated is stored as a table in the database pvt
, and you need to column identifiers Emp1
, Emp2
, Emp3
, Emp4
and Emp5
the rotation value of the row corresponding to a particular vendor. Therefore, the other two columns must be identified. The column that contains the column value ( Emp1
, Emp2
...) Employee
to be rotated is called , and the column that retains the existing value under the column to be rotated is called Orders
. These columns correspond to pivot_column and value_column in the Transact-SQL definition, respectively. The following is the query.
SQL replication
-- 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
The following is a partial result set.
copy
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
...
Please note that it UNPIVOT
is not exactly PIVOT
the reverse operation. PIVOT
Perform aggregation and merge multiple possible lines into one line in the output. UNPIVOT
The result of the original table-valued expression is not reproduced because the rows have been merged. In addition, UNPIVOT
the NULL value in the input disappears in the output. If the value disappears, PIVOT
it means that the original NULL value may already exist in the input before performing the operation.
The Sales.vSalesPersonSalesByFiscalYears
view in the AdventureWorks2012 sample database will use PIVOT
to return the total sales of each salesperson in each fiscal year. To write a view script in SQL Server Management Studio, please find the view corresponding to the AdventureWorks2012 database in the "View" folder in the "Object Explorer" . Right-click the view name, and then select "Script View As".