The World’s Leading Microsoft .NET Magazine
   
 
Jerry Dixon

Pivot Table Data in SQL Server 2000 and 2005

posted Friday, 22 April 2005

I've been asked many times, by clients and friends alike, how to "pivot" a SQL resultset from a set of rows to a set of columns.  This is something that many people do once a blue moon, and then forget how to do it.  So, I decided to place an example on my blog for easy reference.

As I was doing this, I decided to include an example of how SQL Server 2005's new PIVOT operator would change the T-SQL code.  I fully expected that the PIVOT syntax would be easier and cleaner.  Judge the results for yourself.  I will say that the PIVOT syntax wound up being more involved than I expected.

These two SQL statements are intended to list the number of orders placed in the year 2002, with the results broken down by month.  Each month's data is returned in a separate column.

NOTE:  These examples use the new AdventureWorks database in SQL Server 2005.  Originally, I tried to do this with the Northwind database.  The PIVOT operator fails with a syntax error when used against the Northwind database.  This is because the Northwind database is set to SQL Server 2000 compatibility mode.  (Yes, I wasted a good bit of time "remembering" this fact.)

SQL Server 2000
SELECT
     SUM(CASE WHEN MONTH(OrderDate) = 1 THEN 1 END) AS 'January'
     ,SUM(CASE WHEN MONTH(OrderDate) = 2 THEN 1 END) AS 'February'
     ,SUM(CASE WHEN MONTH(OrderDate) = 3 THEN 1 END) AS 'March'
     ,SUM(CASE WHEN MONTH(OrderDate) = 4 THEN 1 END) AS 'April'
     ,SUM(CASE WHEN MONTH(OrderDate) = 5 THEN 1 END) AS 'May'
     ,SUM(CASE WHEN MONTH(OrderDate) = 6 THEN 1 END) AS 'June'
     ,SUM(CASE WHEN MONTH(OrderDate) = 7 THEN 1 END) AS 'July'
     ,SUM(CASE WHEN MONTH(OrderDate) = 8 THEN 1 END) AS 'August'
     ,SUM(CASE WHEN MONTH(OrderDate) = 9 THEN 1 END) AS 'September'
     ,SUM(CASE WHEN MONTH(OrderDate) = 10 THEN 1 END) AS 'October'
     ,SUM(CASE WHEN MONTH(OrderDate) = 11 THEN 1 END) AS 'November'
     ,SUM(CASE WHEN MONTH(OrderDate) = 12 THEN 1 END) AS 'December'
FROM Sales.SalesOrderHeader
WHERE YEAR(OrderDate) = 2002

SQL Server 2005
SELECT
     [1] AS 'January'
     ,[2] AS 'February'
     ,[3] AS 'March'
     ,[4] AS 'April'
     ,[5] AS 'May'
     ,[6] AS 'June'
     ,[7] AS 'July'
     ,[8] AS 'August'
     ,[9] AS 'September'
     ,[10] AS 'October'
     ,[11] AS 'November'
     ,[12] AS 'December'
FROM (
     SELECT 
               MONTH(OrderDate)     AS 'MonthNumber'
               ,COUNT(*)            AS 'OrderCount'
          FROM Sales.SalesOrderHeader
          WHERE YEAR(OrderDate) = 2002
          GROUP BY MONTH(OrderDate)
     ) AS Data
PIVOT(
          SUM(OrderCount)
          FOR MonthNumber IN([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12])
     ) AS PVT

links: digg this    del.icio.us    technorati