MySQL
POSTGRESQL
SQL
SQL SERVER

SQL PIVOT: How to Use a Pivot Table In SQL

intro

Time to look at what the SQL PIVOT clause is and how it is used in changing one table-valued expression into another — let’s get right into it.

Tools used in the tutorial
Tool Description Link
Dbvisualizer DBVISUALIZER
TOP RATED DATABASE MANAGEMENT TOOL AND SQL CLIENT
MySQL logo MySQL
THE MYSQL DATABASE
PostgreSQL logo POSTGRESQL
THE POSTGRESQL DATABASE
SQL Server
SQL Server is a database management system by Microsoft

SQL PIVOT table is a relational operator to create a different view of your data. It also provides the opportunity to create pivot tables and to break down data components into different columns and rows for easy analysis.

This blog will guide you through the process of using the PIVOT SQL operator, including its use cases using a tool like DbVisualizer.

Let’s get started!

What Is PIVOT in SQL?

In SQL, pivoting means rotating data from rows to columns to transform and restructure the dataset. That is the contrary of operators like GROUP BY, where data is often summarized into a single dimension.

Generally, there are two types of pivot tables in SQL:

  1. Dynamic pivot tables: Columns are generated based on the data and are mostly ideal for cases where values are unknown or vary over time (e.g., sales data by month).
  2. Static pivot table: Columns are pre-defined and do not change, making it useful when the structure is predictable.

Time to look at how PIVOT table in SQL works across some database management systems. Note that MySQL and PostgreSQL do not directly support SQL PIVOT table, but do have alternative ways of creating pivot tables. Oracle and SQL Server on the other hand do support pivot tables.

How to Use PIVOT Table in SQL

Implementing PIVOT tables in SQL varies across database management systems (DBMSs) as SQL does not have a universal or standard PIVOT syntax. Each DBMS has its way of creating a pivot table. It is worth noting that the logical structure of a pivot table can be broken into three main parts:

The syntax for the SQL PIVOT operator, which is shown below, has three main parts:

  • SELECT part: The SELECT statement references the returning columns in the SQL pivot table.
  • Subquery part: The subquery contains the table to be included in the SQL pivot table.
  • PIVOT part: The PIVOT operator contains the aggregations and filter to be applied in the pivot table.

Here is the complete structure:

Copy
        
1 -- select the non-pivoted column and the pivoted columns with aliases 2 SELECT 3 [non-pivoted column], 4 [first pivoted column] AS [column name], 5 [second pivoted column] AS [column name], 6 ... 7 FROM 8 ( 9 -- subquery to select the necessary columns from the source table 10 SELECT [columns] 11 FROM [source_table] 12 ) AS source_table 13 PIVOT 14 ( 15 -- pivot operation to aggregate data and transform rows into columns 16 [aggregate_function]([pivot_column]) 17 FOR [pivot_column] IN ([first pivoted column], [second pivoted column], ...) 18 ) AS pivot_table; -- Alias for the result of the pivot operation

Breaking down the syntax:

  • The SELECT statement chooses specific columns from the table.
  • [non-pivoted column] is the column that will not be affected by the pivot operation.
  • [first pivoted column] and [second pivoted column] are the columns that will be pivoted.
  • The AS keyword is used to rename these pivoted columns as [column name].
  • The FROM clause specifies the source of the data, which is a subquery in this case.
  • The SQL subquery selects certain columns from the [source_table].
  • The PIVOT keyword is used to perform the pivot operation.
  • aggregate_function is the operation performed on the pivot column.
  • The FOR keyword specifies the column to be pivoted.
  • The IN clause lists the columns to be included in the pivot operation.
  • AS pivot_table is an SQL alias for the result of the pivot operation.

PIVOT in SQL Server

SQL Server has complete support for the PIVOT operator.

In this example, we will use the PIVOT operator to transform rows into columns and summarize data using aggregate functions like SUM(). Subsequently, we are going to employ also, SQL clauses, such as WHERE, GROUP BY, and ORDER BY for refined data manipulation using this table:

The States demo table in DbVisualizer
The ‘States’ demo table in DbVisualizer

This scenario illustrates how to use the PIVOT operator to filter data for the year 2020 or later (WHERE), group data by city and year (GROUP BY), and sort the data by city (ORDER BY):

Copy
        
1 -- select the state and sales data for the years 1980, 1982,.... 2010 2 SELECT 3 state, 4 [1980] AS Sales_1980, 5 [1982] AS Sales_1982, 6 [1988] AS Sales_1988, 7 [1992] AS Sales_1992, 8 [1999] AS Sales_1999, 9 [2000] AS Sales_2000, 10 [2001] AS Sales_2001, 11 [2010] AS Sales_2010, 12 13 FROM 14 ( 15 -- subquery to select state, year, and sales from the state_sales table 16 SELECT state, year, sales 17 FROM states 18 WHERE year >= 2001 -- filtering 19 GROUP BY state, year, sales -- grouping 20 ) AS src 21 PIVOT 22 ( 23 -- pivot the sales data to have years as columns, averaging the sales over each year 24 SUM(sales) -- aggregating 25 FOR year IN ([1980], [1982], [1988],[1992],[1999],[2000],[2001],[2010]) 26 ) AS pvt;

Execute the query, and you will get the following result:

Dataset transformation using SQL PIVOT
Dataset transformation using SQL PIVOT

PIVOT In Oracle

Similar to SQL Server, Oracle also supports the PIVOT operator to transform rows into columns. However, the syntax of the PIVOT operator in the Oracle database differs slightly from that in SQL Server. The query below shows how the PIVOT operator appears in Oracle. Note that the columns are aliased within the PIVOT operator, unlike the outer SELECT statement in SQL Server.

Copy
        
1 -- outer SELECT to choose all columns resulting from the PIVOT operation 2 SELECT * 3 FROM ( 4 -- inner SELECT to retrieve the raw data of state, year, and sales 5 SELECT state, year, sales 6 FROM sales 7 ) 8 -- PIVOT operation to convert rows to columns 9 PIVOT ( 10 SUM(sales) 11 -- specify the year values to pivot and alias them as Sales_<year> 12 FOR year IN (1980 AS Sales_1980, 1982 AS Sales_1982, 1988 AS Sales_1988, 1992 AS Sales_1992, 1999 AS Sales_1999, 2000 AS Sales_2000, 2001 AS Sales_2001, 2010 AS Sales_2010) 13 ) 14 ORDER BY state;

Creating Pivot Tables in DBMSs Without Native Support

The PostgreSQL database also does not support the SQL PIVOT operator. Therefore, when creating pivot tables, it is important to use the CASE statement with conditional aggregation. The query below is an example of the conditional CASE statements used to create pivot tables in PostgreSQL.

Copy
        
1 -- Select the state and sum the sales data for the years ..... 2 SELECT 3 state, 4 SUM(CASE WHEN year = 1980 THEN sales ELSE 0 END) AS Sales_1980, 5 SUM(CASE WHEN year = 1982 THEN sales ELSE 0 END) AS Sales_1982, 6 SUM(CASE WHEN year = 1988 THEN sales ELSE 0 END) AS Sales_1988, 7 SUM(CASE WHEN year = 1992 THEN sales ELSE 0 END) AS Sales_1992, 8 SUM(CASE WHEN year = 1999 THEN sales ELSE 0 END) AS Sales_1999, 9 SUM(CASE WHEN year = 2000 THEN sales ELSE 0 END) AS Sales_2000, 10 SUM(CASE WHEN year = 2001 THEN sales ELSE 0 END) AS Sales_2001, 11 SUM(CASE WHEN year = 2010 THEN sales ELSE 0 END) AS Sales_2010 12 FROM 13 states 14 GROUP BY 15 state; 16 ORDER BY 17 state;

Run the query in DbVisualizer, and you will get:

Pivoting in PostgreSQL
Pivoting in PostgreSQL

Breaking down the code above:

  • state is selecting the column named "state" from the database.
  • SUM(CASE WHEN year = 1980 THEN sales ELSE 0 END) AS Sales_1980, is summing the sales for the year 1980.
  • SUM(CASE WHEN year = 1982 THEN sales ELSE 0 END) AS Sales_1982, is summing the sales for the year 1982.
  • SUM(CASE WHEN year = 1988 THEN sales ELSE 0 END) AS Sales_1988 is summing the sales for the year 1988. etc.
  • FROM states is specifying the table "states" to select from.
  • GROUP BY state is grouping the selected data by the "state" column.
  • ORDER BY state; is ordering the output by the "state" column in ascending order.

Dynamic Pivoting In SQL

In SQL pivoting, dynamic pivot tables provide compliance by generating columns based on data values. This technique is especially valuable when we have unknown or variable columns. Let’s look at how dynamic pivoting works in SQL Server using dynamic SQL:

Copy
        
1 -- block declaration to execute PL/pgSQL code in an anonymous code block 2 DO 3 $$ 4 DECLARE 5 cols text; -- variable to store the list of columns for the dynamic query 6 query text; -- variable to store the dynamic SQL query 7 BEGIN 8 -- get distinct years and construct the list of SUM(CASE...) statements 9 SELECT STRING_AGG(DISTINCT 'SUM(CASE WHEN year = ' || year || ' THEN sales ELSE 0 END) AS "Sales_' || year || '"', ', ') 10 INTO cols 11 FROM states; 12 13 -- construct the dynamic PIVOT query 14 query := 'SELECT state, ' || cols || ' FROM states GROUP BY state ORDER BY state'; 15 16 -- execute the dynamic PIVOT query 17 EXECUTE query; 18 END 19 $$;

Breaking down this code:

  • The DO statement is used to execute an anonymous code block in PostgreSQL.
  • The DECLARE section is used to define two variables, cols and query, both of type text.
  • The BEGIN statement marks the start of the code block.
  • A SELECT statement is used to create a list of SUM(CASE...) statements for each distinct year in the city_sales table.
  • The STRING_AGG function is used to concatenate the output into a single string, which is stored in the cols variable.
  • The query variable is then assigned a dynamic SQL query, which includes the cols variable.
  • The EXECUTE statement runs the dynamic SQL query stored in the query variable.
  • The END statement marks the end of the code block and the $ symbol closes the anonymous code block.

Not only can dynamic pivoting be done in PostgreSQL, it can also be done in other DBMSs such as Oracle, MySQL, etc. Feel free to learn how to implement dynamic pivoting in these other database management systems.

It’s a wrap!

Conclusion

Pivot tables are essential for converting raw data into structured, insightful views, especially when summarizing or aggregating information for analysis. While some DBMSs like SQL Server or Oracle provide built-in PIVOT operators, others, such as MySQL, require manual workarounds using CASE statements and aggregate functions. These methods are flexible but can lead to lengthy and complex queries, especially as datasets grow.

If you're working with MySQL or any DBMS without native pivot support, a tool like DbVisualizer can make your life easier. With just a few clicks, you can format, organise, and manage even the most intricate SQL queries. DbVisualizer’s user-friendly interface ensures your long and nested pivot queries remain readable and maintainable, saving you time and reducing errors.

Before closing, follow our blog for more updates, and we’ll see you in the next one.

FAQ

What is a Pivot table in SQL and why would I use one?

A pivot table is a data summarization tool that allows you to transform and reorganize rows into columns based on certain criteria. In SQL, pivot tables help summarize and analyze data across multiple dimensions, like summarizing sales by region and month.

What is the difference between PIVOT and UNPIVOT in SQL?

PIVOT converts rows into columns and is commonly used to summarize and aggregate data in a tabular format, where unique values in a row are turned into new column headers. UNPIVOT, on the other hand, converts columns into rows. So basically, it is the reverse of a PIVOT operation and is used to normalize or restructure data into a simpler row-based format.

Does PostgreSQL have a built-in PIVOT function?

No, PostgreSQL doesn’t have a direct PIVOT function like SQL Server. However, you can achieve pivoting in PostgreSQL using CASE statements or the crosstab() function from the tablefunc extension, which allows you to transform row-based data into a pivoted table format.

Does MySQL have a built-in PIVOT function like other databases?

No, MySQL does not have a built-in PIVOT function like SQL Server or Oracle. However, you can achieve the same pivot functionality by combining CASE statements, aggregate functions, and sometimes dynamic SQL.

Dbvis download link img
About the author
Leslie S. Gyamfi.
Leslie S. Gyamfi
Leslie Gyamfi is a mobile/web app developer with a passion for creating innovative solutions. He is dedicated to delivering high-quality products and technical articles. You can connect with him on LinkedIn
The Table Icon
Sign up to receive The Table's roundup
More from the table
Title Author Tags Length Published
title

When, How, and Why to Use the Truncate SQL Statement

author Lukas Vileikis tags DbVisualizer MySQL SQL 6 min 2025-03-11
title

MySQL ALTER TABLE Statement: Definitive Guide

author Antonello Zanini tags ALTER TABLE MySQL 11 min 2025-03-06
title

A Complete Guide to the SQL CREATE INDEX Statement

author Antonello Zanini tags MySQL ORACLE POSTGRESQL SQL SQL SERVER 7 min 2025-03-05
title

A Complete Guide to the Order of Execution in SQL

author Antonello Zanini tags MySQL ORACLE POSTGRESQL SQL SQL SERVER 9 min 2025-03-03
title

MySQL NOW Function: Get the Current Date and Time

author Antonello Zanini tags DATETIME MySQL 5 min 2025-02-27
title

A Complete Guide to the MySQL CTE Mechanism

author Antonello Zanini tags MySQL 10 min 2025-02-26
title

SQL Operators: A Complete Walkthrough

author Lukas Vileikis tags DbVisualizer MySQL SQL 4 min 2025-02-25
title

How to Truncate Many Tables In SQL at Once

author Antonello Zanini tags MySQL ORACLE POSTGRESQL SQL SQL SERVER 6 min 2025-02-24
title

PostgreSQL Truncate Table Reset Sequence Guide

author Antonello Zanini tags POSTGRESQL 6 min 2025-02-17
title

Clustered vs Non-Clustered Index: Complete SQL Guide

author Antonello Zanini tags MySQL ORACLE POSTGRESQL SQL SQL SERVER 8 min 2025-02-13

The content provided on dbvis.com/thetable, including but not limited to code and examples, is intended for educational and informational purposes only. We do not make any warranties or representations of any kind. Read more here.