The PIVOT operator in SQL
The PIVOT operator in SQL Server is an advanced relational operator that helps transforming and reorganizing data in a tabular format, enhancing analytical capabilities. It enables the conversion of unique data from rows into columns, thereby allowing for a more streamlined presentation of aggregated data. This transformation is particularly beneficial in generating cross-tabular reports where data comparison across distinct categories is essential, simplifying complex reporting requirements in data-driven environments.
Here’s a simple example of using the `PIVOT` command in SQL Server. Suppose you have a table named `Sales` with the following structure:
| Product | Quarter | SalesAmount |
|---------|---------|-------------|
| A | Q1 | 100 |
| A | Q2 | 150 |
| A | Q3 | 200 |
| A | Q4 | 250 |
| B | Q1 | 120 |
| B | Q2 | 180 |
| B | Q3 | 240 |
| B | Q4 | 300 |
You want to transform this data to show total sales for each product per quarter as columns. Here’s how you can achieve that using the `PIVOT` command:
SELECT Product, [Q1], [Q2], [Q3], [Q4]
FROM ( SELECT Product, Quarter, SalesAmount FROM Sales ) AS SourceTable
PIVOT ( SUM(SalesAmount) FOR Quarter IN ([Q1], [Q2], [Q3], [Q4]) ) AS PivotTable;
In this query (The PIVOT operator in SQL):
- 1. The subquery SourceTable selects the relevant columns from the Sales table.
- 2. The PIVOT operation specifies that we want to aggregate the SalesAmount using the SUM function, and change the Quarter values (Q1, Q2, Q3, Q4) into columns.
- 3. The final result shows total sales for each product across the quarters, with the quarter names as column headers.
The result will be:
| Product | Q1 | Q2 | Q3 | Q4 |
|---------|-----|-----|-----|-----|
| A | 100 | 150 | 200 | 250 |
| B | 120 | 180 | 240 | 300 |
Employing PIVOT involves specifying an aggregation function and a column source from which values will be extracted. A typical use case requires defining the columns to be pivoted and the aggregation logic, such as SUM or AVG, that will be applied to them. This operation facilitates the summarization of large datasets, aiding in data interpretation by highlighting trends, anomalies, and insights that would otherwise remain obscured in traditional row-oriented datasets. It effectively reduces the cognitive load required to analyze and interpret sprawling data representations. The PIVOT operator in SQL.
In SQL Server, strategic use of PIVOT hinges on a deep understanding of the underlying dataset structure and analytical goals. It’s essential to carefully design the column selection and aggregation criteria to ensure meaningful data transformations that align with the queries’ analytic objectives. By leveraging PIVOT, database professionals can empower stakeholders to make data-driven decisions with high precision and clarity, capitalizing on SQL Server’s robust capabilities for sophisticated data manipulation and presentation.
Here the real example a lange table of date
SELECT top 100
[CustomerIdEx] as Customer
,[Dt_ym]
,[ErpValueNet_sum]
FROM [OnnShop20REC].[onn].[DBCust_stat_baskets]
where Dt_ym >= '2023-09-01' order by 1
As we can see, all months and corresponding sales for certain customer is presented in rows.

The PIVOT operator in SQL
If we would like to have months in columns and every customer in rows, then we must apply PIVOT
select
[CustomerIdEx],
[2023-09-01],
[2023-10-01],
[2023-11-01],
[2023-12-01],
[2024-01-01],
[2024-02-01],
[2024-03-01],
[2024-04-01],
[2024-05-01],
[2024-06-01],
[2024-07-01],
[2024-08-01],
[2024-09-01],
[2024-10-01] from (
SELECT top 100
[CustomerIdEx]
,[Dt_ym]
,[ErpValueNet_sum]
FROM [OnnShop20REC].[onn].[DBCust_stat_baskets]
where Dt_ym >= '2023-09-01' order by 1
) as p
pivot
( sum([ErpValueNet_sum])
for [Dt_ym] in (
[2023-09-01],
[2023-10-01],
[2023-11-01],
[2023-12-01],
[2024-01-01],
[2024-02-01],
[2024-03-01],
[2024-04-01],
[2024-05-01],
[2024-06-01],
[2024-07-01],
[2024-08-01],
[2024-09-01],
[2024-10-01] )
) as pvt
order by pvt.[CustomerIdEx]
You can read more about PIVOT here: https://learn.microsoft.com/en-us/sql/t-sql/queries/from-using-pivot-and-unpivot?view=sql-server-ver16

We can also build a dynamic sql for similar operations, The PIVOT operator in SQL.
declare @sql_str as nvarchar(max);
declare @key_column as nvarchar(20);
declare @result_columns as nvarchar(max);
declare @source_data as nvarchar(max);
declare @agg_formula as nvarchar(max);
declare @column_field as nvarchar(20);
set @source_data = N'SELECT [Dt_ym]
,[CustomerIdEx]
,[ErpValueNet_sum]
FROM [DBCust_stat_baskets]
where Dt_ym >= ''2023-09-01'' '
set @key_column = '[CustomerIdEx]';
select @result_columns = string_agg(d.[Dt_ym],',') from (
select [Dt_ym] FROM [DBCust_stat_baskets] where Dt_ym >= '2023-09-01' group by [Dt_ym] ) as d
set @result_columns = '[' + replace(@result_columns,',','],[') +']'
;
set @agg_formula = N'sum([ErpValueNet_sum])';
set @column_field = N'[Dt_ym]'
set @sql_str = 'select ' + @key_column + ',';
set @sql_str = @sql_str + @result_columns + ' from (';
set @sql_str = @sql_str + @source_data + ') as p PIVOT ( ' ;
set @sql_str = @sql_str + @agg_formula + ' for ' + @column_field + ' in ( ' + @result_columns + ' )'
set @sql_str = @sql_str + ' ) as pvt '
EXEC sp_executesql @sql_str;
print @sql_str;
In this example, we’ll write a dynamic SQL (The PIVOT operator in SQL) query to handle scenarios where the pivot columns aren’t known in advance. Dynamic SQL is particularly useful for creating flexible queries that adapt to varying data structures, such as dynamically-generated columns for a pivot operation. Below is a detailed explanation of a dynamic SQL approach to perform a pivot operation in SQL Server.
Dynamic SQL allows for building queries based on dynamic parameters or outputs from other SQL statements. For example, consider a `Sales` table where the `Quarter` values may vary and need to be dynamically determined for the pivot operation. Initially, you’ll retrieve distinct `Quarter` values from the `Sales` table into a string of comma-separated values for use as pivot columns. This can be achieved using the `STUFF` and `FOR XML PATH` techniques to concatenate column names.
sql
DECLARE @columns NVARCHAR(MAX), @sql NVARCHAR(MAX);
-- Dynamically create a string of column names
SELECT @columns = STUFF((SELECT DISTINCT ',' + QUOTENAME(Quarter)
FROM Sales
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '');
-- Construct the dynamic SQL query
SET @sql = N'SELECT Product, ' + @columns + '
FROM (SELECT Product, Quarter, SalesAmount FROM Sales) AS SourceTable
PIVOT (SUM(SalesAmount) FOR Quarter IN (' + @columns + ')) AS PivotTable;';
-- Execute the dynamic SQL query
EXEC sp_executesql @sql;
This code snippet first retrieves unique quarter names dynamically, then builds and executes a pivot query. The PIVOT operator in SQL. It showcases dynamic SQL’s power in handling variable datasets, offering a flexible, adaptable mechanism for data transformation where column values may change over time or differ across environments.
sp_executesql and EXEC
In SQL Server, both `sp_executesql` and `EXEC` can be used to execute dynamic SQL queries, but they have distinct differences and use cases (The PIVOT operator in SQL):
Parameterization
sp_executesql: This is a system stored procedure that allows for parameterized queries. You can define and pass parameters, making the SQL execution more secure and efficient by helping to prevent SQL injection attacks and promoting better query plan reuse. For instance, you can execute a query with variable inputs by defining parameters like this:
DECLARE @sql NVARCHAR(MAX), @paramDefinition NVARCHAR(MAX);
SET @sql = N'SELECT * FROM Sales WHERE Product = @ProductName';
SET @paramDefinition = N'@ProductName NVARCHAR(50)';
EXEC sp_executesql @sql, @paramDefinition, @ProductName = 'A';
EXEC: This command can execute SQL statements or stored procedures but doesn’t inherently support parameterization. It is commonly used for running stored procedures or executing SQL strings directly. If you use it with dynamic SQL, concatenation of strings may be necessary, which can expose the application to SQL injection risks. The PIVOT operator in SQL.
Execution Plan Reuse of sp_executesql and exec
- sp_executesql: Supports better execution plan reuse because it maintains parameterized queries. Since the structure of the query remains consistent across executions with only parameter values changing, SQL Server can efficiently reuse cached execution plans, optimizing performance.
- EXEC: When using dynamic SQL with EXEC, frequent changes in concatenated queries can lead to the creation of multiple execution plans, each tailored to specific string values. This reduces execution plan efficiency and increases resource utilization.
Security and Safety
- sp_executesql: Offers more security advantages by allowing parameterization, which reduces the risk of SQL injection. Parameters are explicitly defined and separated from the query logic.
- EXEC: More prone to SQL injection attacks if not used carefully with input validation and escaping since parameters are often included through string concatenation.
In summary, sp_executesql is generally preferable for executing dynamic SQL as it provides robust support for parameterized queries, enhancing both security and performance through execution plan reuse. On the other hand, EXEC is simpler but less secure and efficient for complex dynamic SQL scenarios. The PIVOT operator in SQL.
