SQL Pivot Tables


PIVOT rotates a table-valued expression by turning the unique values from one column in the expression into multiple columns in the output, and performs aggregations where they are required on any remaining column values that are wanted in the final output.

A Note on Performance

Performing a PIVOT on a large table takes a lot of resources. If at all possible, SELECT your data into a temp table or table variable. For data sets containing more than a few hundred rows, use a temp table. Temp tables (as opposed to table variables) allow indexing, which can help your PIVOT or other aggregations run faster.

Sample Data

In the following examples this table will be referred to as #Temp.


Sample Pivot

SELECT [Affiliate], [January], [February], [March]
FROM (SELECT [Affiliate], [Month], [Sales] FROM #Temp) AS T
PIVOT(SUM([Sales]) FOR [Month] IN ([January], [February], [March])) AS PVT

Sample Result Set


Dissecting the Statement

SELECT [Affiliate], [January], [February], [March]

  • These are the names of the columns for the Result Set
  • Plain English: Show columns named…

FROM (SELECT [Affiliate], [Month], [Sales] FROM #Temp) AS T

  • The data we want to pull in to pivot
  • Notice [Month], which contains the values ‘January’, ‘February’, and ‘March’
  • Plain English: Pull data from this table

PIVOT(SUM([Sales]) FOR [Month] IN ([January], [February], [March])) AS PVT

  • An aggregate function is required
    • With this example, we want to add up the [Sales] by [Month]
  • FOR is used to find the [Sales] as they relate to [Month]
  • IN is used to find the values to group the aggregation (SUM in this case)
  • Plain English: Group [sales] by [month], where the month is a given value

Helpful Tips

  • Use isNull() to replace NULL with a value
    • Syntax: isNull([ColumnName], {return value if null}) AS ‘ColumnName’
    • Example: isNull([Sales], 0) AS ‘Sales’
      • Returns a 0 if [Sales] is NULL
      • Don’t forget to name your column or it will be returned as “(no column name)”
    • Usage: Use for values that are displayed in the Result Set
      • Simple Select: SELECT [CustomerID] , isNull([CommAmt], 0) FROM
      • Aggregated Select: GROUP BY isNull([CommAmt], 0)
      • PIVOT Select: SELECT [Affiliate], isNull([January], 0) AS ‘January’, …
    • Data Type: The replacement value must be the same data type as the column
      • Using the above examples, we surmise that [CommAmt] is DECIMAL
      • We must return a DECIMAL value (a number)
      • We cannot return ‘No Sales’ as that would be a string (NVARCHAR)
  • Use MONTH() to extract the month from a date
    • The sample table was created using a case statement as MONTH([Date]) returns a value 0-12 as part of the SELECT statement:
    • ,CASE MONTH([Date])
      WHEN 1 THEN ‘January’
      WHEN 2 THEN ‘February’
      WHEN 3 THEN ‘March’
      END AS ‘Month’

T-SQL Primer

About T-SQL

Transact-SQL is central to using SQL Server. All applications that communicate with an instance of SQL Server do so by sending Transact-SQL statements to the server, regardless of the user interface of the application.

Download T-SQL

Microsoft SQL Server 2014 Express is a free, feature-rich edition of SQL Server that is ideal for learning, developing, powering desktop, web & small server applications, and for redistribution by ISVs. The SQL Server 2014 Express release includes the full version of SQL Server 2014 Management Studio instead of SQL Server 2014 Management Studio Express.

Starting T-SQL

SQL Server Management Studio is not installed by default. If Management Studio is unavailable, install it by running Setup. Management Studio is not available with SQL Server Express. Management Studio Express is available as a free download from the Microsoft Download Center, but has a different user interface than is described in this tutorial.

To open SQL Server Management Studio

    • On the Start menu, point to All Programs, point to Microsoft SQL Server 2014, and then click SQL Server Management Studio.
    • In the Connect to Server dialog box, verify the default settings, and then click Connect. To connect, the Server name box must contain the name of the computer where SQL Server is installed. If the Database Engine is a named instance, the Server name box should also contain the instance name in the format <computer_name>\<instance_name>.

Hello World!

Retrieves rows from the database and enables the selection of one or many rows or columns from one or many tables in SQL Server. The full syntax of the SELECT statement is complex, but the main clauses can be summarized as:
[ WITH <common_table_expression>]
SELECT select_list [ INTO new_table ]
[ FROM table_source ] [ WHERE search_condition ]
[ GROUP BY group_by_expression ]
[ HAVING search_condition ]
[ ORDER BY order_expression [ ASC | DESC ] ]
The UNION, EXCEPT and INTERSECT operators can be used between queries to combine or compare their results into one result set.

  1. Open SQL Server Management Studio
  2. Click File, point to New, and then select Query with Current Connection
  3. Type SELECT 'Hello World!'
  4. Execute the script by pressing [F5]
"Hello World!"


Variables are declared in the body of a batch or procedure with the DECLARE statement and are assigned values by using either a SET or SELECT statement. Cursor variables can be declared with this statement and used with other cursor-related statements. After declaration, all variables are initialized as NULL, unless a value is provided as part of the declaration.

DECLARE @message AS nvarchar(max)
SET @message = 'Hello World!'
SELECT @message
"Hello World!"


Like functions in programming languages, SQL Server user-defined functions are routines that accept parameters, perform an action, such as a complex calculation, and return the result of that action as a value. The return value can either be a single scalar value or a result set.

Encloses a series of Transact-SQL statements so that a group of Transact-SQL statements can be executed. BEGIN and END are control-of-flow language keywords.

Signals the end of a batch of Transact-SQL statements to the SQL Server utilities.

	DECLARE @message AS nvarchar(max)
	SET @message = 'Hello World!'
	SELECT @message

Attaching a Sample Database

About this release
This release consolidates AdventureWorksDW databases for SQL Server 2012, 2008R2 and 2008 versions to one page. Each zip file contains an mdf database file and an ldf log file. This should make it easier to find and download AdventureWorksDW databases since all OLAP versions are on one page.

An AdventureWorksDW database can be installed by attaching the database, or using the CREATE DATABASE statement.
To attach an AdventureWorks database

  1. Download a database for your SQL Server version.
  2. Unzip the database (mdf) file and log (ldf) file.
  3. From Microsoft SQL Server Management Studio, connect to a SQL Server instance.
  4. Right click Databases.
  5. Click Attach.
  6. Click the Add button.
  7. Locate the AdventureWorksDW database mdf file. For instance, AdventureWorksDW2012_Data.mdf.
  8. Click the OK button on the Locate Database Files dialog window.
  9. Click the OK button on the Attach Databases dialog window to attach the database.

From SQL Server Management Studio, execute the following T-SQL:
Example T-SQL

-- Select ALL records from the AdventureWorks0212 database in table Sales.Store
SELECT * FROM [AdventureWorks2012].[Sales].[Store]

Further Reading

Documentation for SQL Server 2014 Tools and Add-in Components

  • The table lists SQL Server tools and add-ins, and provides links to additional documentation in the MSDN Library.

W3Schools SQL Tutorial

  • SQL tutorial will teach you how to use SQL to access and manipulate data in: MySQL, SQL Server, Access, Oracle, Sybase, DB2, and other database systems.