The SQL Server Pivot is one of the most useful operators to convert the Row values into Column names or, say, rotating tables. While rotating the table or the Pivot Table, only the column values that are involved in Grouping or Aggregation are allowed to be moved. This Pivot Table tutorial will help you understand how to use the pivot table wizard.
USE AdventureWorks2014
GO
SELECT PROD.Name,
YEAR(OrdHead.OrderDate) AS [Order Year],
SUM(Details.OrderQty) AS [Order Quantity]
FROM Sales.SalesOrderDetail AS Details
INNER JOIN
Production.Product AS PROD ON
Details.ProductID = PROD.ProductID
INNER JOIN
Sales.SalesOrderHeader AS OrdHead ON
Details.SalesOrderID = OrdHead.SalesOrderID
GROUP BY
PROD.Name,
YEAR(OrdHead.OrderDate)
ORDER BY [Order Year]
We’re going to copy the original data into a new table. This will prevent any problems if our source data changes. I think it’s essential that you master the SQL Server PIVOT clause as it can be used to perform calculations on columns of data. When you do this, you are using the SELECT INTO statement. Use the PIVOT function to change data into columns.
Here’s a look at our new table data:
PIVOT Operator Example
This example will convert the date to separate months and years so that each row of data will contain a month and year value. If you’re ordering by Product Name, your Order quantities will be separated into columns based on the Year.
SELECT Name,[2011], [2012], [2013], [2014]
FROM (
SELECT [Name]
,[Order Year]
,[Order Quantity]
FROM [PSource]
) AS SOURCE
PIVOT
(
SUM([Order Quantity]) FOR [Order Year]
IN ([2011], [2012], [2013], [2014])
) AS [Result]
ORDER BY Name
Using the Select query we just wrote, you can retrieve all the data from the SalesOrders table. Please refer to the SELECT statement and the SELECT INTO statement in SQL Server.
After this, the remaining questions after the SOURCE will be converted into columns using the aggregate function SUM and then pivoted. This query displays the output.
SELECT Name,[2011], [2012], [2013], [2014]
You need to use the following query to get the data into the format that you require it in.
USE AdventureWorks2014
GO
SELECT Name,[2011], [2012], [2013], [2014]
FROM
(
SELECT PROD.Name,
YEAR(OrdHead.OrderDate) AS OrderYear,
SUM(Details.OrderQty) AS OrderQuantity
FROM Sales.SalesOrderDetail AS Details
INNER JOIN Production.Product AS PROD
ON Details.ProductID = PROD.ProductID
INNER JOIN Sales.SalesOrderHeader AS OrdHead
ON Details.SalesOrderID = OrdHead.SalesOrderID
GROUP BY PROD.Name,YEAR(OrdHead.OrderDate)
) AS SOURCE
PIVOT( SUM(OrderQuantity) FOR OrderYear
IN ([2011], [2012], [2013], [2014])
) AS Result
ORDER BY Name
Another example
Suppose that you are getting all your information from one table. If your source data doesn’t include any Joins and Grouping. You could try this approach:
SELECT Name,[2011], [2012], [2013], [2014]
FROM [PSource]
PIVOT
(
SUM([Order Quantity]) FOR [Order Year]
IN ([2011], [2012], [2013], [2014])
) AS [Result]
ORDER BY Name
PIVOT Alternative
This alternative query example is purely for interview purposes. You should start by reading the question carefully. For example, if the question asks you to convert a row into column format, you don’t have to start.
SELECT
Name
,SUM(CASE WHEN [Order Year] = 2011 THEN [Order Quantity] ELSE 0 END)AS [2011]
,SUM(CASE WHEN [Order Year] = 2012 THEN [Order Quantity] ELSE 0 END)AS [2012]
,SUM(CASE WHEN [Order Year] = 2013 THEN [Order Quantity] ELSE 0 END)AS [2013]
,SUM(CASE WHEN [Order Year] = 2014 THEN [Order Quantity] ELSE 0 END)AS [2014]
FROM [PSource]
GROUP BY Name
ORDER BY Name
If you want to use the same functionality on your original data, you need to use this query:
USE AdventureWorks2014
GO
SELECT
PROD.Name
,SUM(CASE WHEN YEAR(OrdHead.OrderDate) = 2011 THEN (Details.OrderQty) ELSE 0 END)AS [2011]
,SUM(CASE WHEN YEAR(OrdHead.OrderDate) = 2012 THEN (Details.OrderQty) ELSE 0 END)AS [2012]
,SUM(CASE WHEN YEAR(OrdHead.OrderDate) = 2013 THEN (Details.OrderQty) ELSE 0 END)AS [2013]
,SUM(CASE WHEN YEAR(OrdHead.OrderDate) = 2014 THEN (Details.OrderQty) ELSE 0 END)AS [2014]
FROM Sales.SalesOrderDetail AS Details
INNER JOIN Production.Product AS PROD
ON Details.ProductID = PROD.ProductID
INNER JOIN Sales.SalesOrderHeader AS OrdHead
ON Details.SalesOrderID = OrdHead.SalesOrderID
GROUP BY PROD.Name
ORDER BY Name