Guide
Dynamic PIVOT in SQL Server: Auto-Generate Column Lists
Bill Crawford — Guide — February 2026 — 9 min read · Last updated October 05, 2025
Static vs Dynamic PIVOT
A static PIVOT query hardcodes the column values in the IN clause. This works when the set of values is fixed — quarters Q1–Q4, months Jan–Dec, statuses Active/Inactive. But when new values appear in your data — a new product, a new region, a new status — the static query misses them until you update it manually.
A dynamic PIVOT solves this by querying the distinct values at runtime and building the IN clause dynamically using EXEC sp_executesql or EXEC(@sql).
How Dynamic PIVOT Works
The pattern has three steps:
- Query distinct values — select the distinct values from your pivot column and concatenate them into a comma-separated, bracket-quoted string
- Build the SQL string — embed that column list into a PIVOT query template as a string variable
- Execute the SQL string — run the assembled query with
EXEC(@sql) or sp_executesql
Using the Generator
Provide the source table name, the pivot column (whose values become headers), and the value column to aggregate.
Select SUM, COUNT, AVG, MIN, or MAX.
These stay as rows in the output.
The generator produces a complete dynamic PIVOT script with the column-discovery query and EXEC block.
Full T-SQL Example
DECLARE @cols NVARCHAR(MAX);
DECLARE @sql NVARCHAR(MAX);
-- Step 1: build the column list
SELECT @cols = STRING_AGG(QUOTENAME(Quarter), ',')
FROM (SELECT DISTINCT Quarter FROM sales) AS t;
-- Step 2: build the pivot query
SET @sql = N'
SELECT Region,' + @cols + N'
FROM (
SELECT Region, Quarter, Revenue
FROM sales
) AS src
PIVOT (
SUM(Revenue)
FOR Quarter IN (' + @cols + N')
) AS pvt
ORDER BY Region;';
-- Step 3: execute
EXEC sp_executesql @sql;
Security: SQL Injection
Important: Dynamic SQL is vulnerable to SQL injection if column values come from user input. Always use QUOTENAME() to wrap column values — it escapes brackets and prevents injection. Never concatenate raw user input into dynamic SQL.
Tips
- Use
STRING_AGG (SQL Server 2017+) or STUFF/FOR XML PATH for older versions to build the column list.
- Add an
ORDER BY inside the column-discovery query to control the column order.
- Test with a static PIVOT first — get the logic right, then make it dynamic.
- Dynamic PIVOT results can't be referenced by column name in the outer query because the schema isn't known at parse time.
Frequently Asked Questions
Does dynamic PIVOT work in other databases?▼
No — sp_executesql and QUOTENAME are SQL Server specific. PostgreSQL uses dynamic SQL via PL/pgSQL with EXECUTE. MySQL uses prepared statements. The pattern is the same but the syntax differs.
What version of SQL Server does STRING_AGG require?▼
STRING_AGG was introduced in SQL Server 2017. For SQL Server 2012–2016, use STUFF with FOR XML PATH to concatenate the column list.
Why do I get an error about an invalid column name?▼
This usually means the dynamic SQL is being compiled before the column list is built, which isn't possible at parse time. Always use EXEC or sp_executesql to run dynamic SQL — it's compiled at execution time, not parse time.
Can I add column totals to a dynamic pivot?▼
Yes — add a Grand Total column by unioning or computing totals within the dynamic SQL string before executing it.
Bill Crawford is a data systems developer and technical founder with over 30 years of professional experience in accounting, finance, and business operations.
He holds a Bachelor's degree in Accounting and has spent more than three decades working within financial and operational environments. Over the past 10 years, he has been heavily involved in the development, implementation, and refinement of financial and enterprise data systems for both Fortune 500 companies and smaller organizations.
His work bridges finance and technology — combining deep domain knowledge in structured reporting and accounting workflows with hands-on SQL development and database architecture experience.
Bill founded DataConversionCenter.com to build practical, browser-based tools that simplify complex data challenges, including:
- SQL query construction and formatting
- Pivot table logic generation
- Cross-dialect SQL conversion
- Structured data modeling
- Financial data normalization
- File format transformation
Rather than focusing on theoretical examples, his tools and articles are informed by real-world challenges encountered in enterprise reporting systems, financial databases, and operational data environments.
Professional Background
- Bachelor's Degree in Accounting
- 30+ years in accounting and finance
- 10+ years deeply involved in financial and enterprise systems development
- Experience supporting Fortune 500 and small-to-mid-sized organizations
- Hands-on SQL development across relational database platforms
Bill's mission is to reduce friction in data workflows — particularly for professionals working with structured financial, operational, and reporting data.