WORDPRESS 이것저것 파헤치기
  • about me
  • wordpress
    • theme
    • plugin
    • tip
  • programming
    • .net
    • sql
    • javascript
    • mobile
    • etc
  • reference
  • contact

Home » programming » Dynamic PIVOT queries in SQL Server

Jun 18

Dynamic PIVOT queries in SQL Server

By : admin/ Tags : Dynamic Pivot, Sql, T-Sql/Category : programming, sql/0 Comment
Problem

Pivoting (or producing a “cross-tab”) is a common reporting requirement – data is stored in columns and you need to present it in rows. This was a nice feature that was added to SQL Server, but you don’t always know all of the values you need to pivot on.? In this tip we look at how you can dynamically create the pivot command to handle these unknown values.

Solution

In these cases it may make sense to construct a dynamic pivot. Let’s assume the following simple schema:

USE tempdb;
GO
CREATE TABLE dbo.Products
(
  ProductID INT PRIMARY KEY,
  Name      NVARCHAR(255) NOT NULL UNIQUE
  /* other columns */
);
INSERT dbo.Products VALUES
(1, N'foo'),
(2, N'bar'),
(3, N'kin');
CREATE TABLE dbo.OrderDetails
(
  OrderID INT,
  ProductID INT NOT NULL
    FOREIGN KEY REFERENCES dbo.Products(ProductID),
  Quantity INT
  /* other columns */
);
INSERT dbo.OrderDetails VALUES
(1, 1, 1),
(1, 2, 2),
(2, 1, 1),
(3, 3, 1);

A query to obtain each product’s total quantity ordered would look something like this (ignoring details about order date, etc.):

SELECT p.Name, Quantity = SUM(o.Quantity)
  FROM dbo.Products AS p
  INNER JOIN dbo.OrderDetails AS o
  ON p.ProductID = o.ProductID
  GROUP BY p.Name;

And in this case the results would look like this:

Actual results from grouped query

But what if the results needed to look like this?

Desired results for report

We could write a hard-coded PIVOT query, but only if we know all of the potential product names:

SELECT p.[foo], p.[bar], p.[kin]
FROM
(
  SELECT p.Name, o.Quantity
   FROM dbo.Products AS p
   INNER JOIN dbo.OrderDetails AS o
   ON p.ProductID = o.ProductID
) AS j
PIVOT
(
  SUM(Quantity) FOR Name IN ([foo],[bar],[kin])
) AS p;

If we add a new product, this PIVOT query no longer gives us the complete story. And we certainly don’t want to have to go back and edit these queries every time we add a product (never mind when a product’s name is changed). So consider some new data:

INSERT dbo.Products SELECT 4, N'blat';
INSERT dbo.OrderDetails SELECT 4,4,5;

Obviously the hard-coded PIVOT query is not going to pick up this new product:

SELECT p.[foo], p.[bar], p.[kin]
FROM
(
  SELECT p.Name, o.Quantity
   FROM dbo.Products AS p
   INNER JOIN dbo.OrderDetails AS o
   ON p.ProductID = o.ProductID
) AS j
PIVOT
(
  SUM(Quantity) FOR Name IN ([foo],[bar],[kin])
) AS p;

Results are the same as before:

Results from hard-coded PIVOT

Enter dynamic SQL. Typically frowned upon, this is one of the scenarios where you are likely to make a strong case for its use. We can simply build the output / pivot column list at runtime, and append it to the rest of the query:

DECLARE @columns NVARCHAR(MAX), @sql NVARCHAR(MAX);
SET @columns = N'';
SELECT @columns += N', p.' + QUOTENAME(Name)
  FROM (SELECT p.Name FROM dbo.Products AS p
  INNER JOIN dbo.OrderDetails AS o
  ON p.ProductID = o.ProductID
  GROUP BY p.Name) AS x;
SET @sql = N'
SELECT ' + STUFF(@columns, 1, 2, '') + '
FROM
(
  SELECT p.Name, o.Quantity
   FROM dbo.Products AS p
   INNER JOIN dbo.OrderDetails AS o
   ON p.ProductID = o.ProductID
) AS j
PIVOT
(
  SUM(Quantity) FOR Name IN ('
  + STUFF(REPLACE(@columns, ', p.[', ',['), 1, 1, '')
  + ')
) AS p;';
PRINT @sql;
EXEC sp_executesql @sql;

Results:

SELECT p.[foo], p.[bar], p.[kin], p.[blat]
FROM
(
  SELECT p.Name, o.Quantity
   FROM dbo.Products AS p
   INNER JOIN dbo.OrderDetails AS o
   ON p.ProductID = o.ProductID
) AS j
PIVOT
(
  SUM(Quantity) FOR Name IN ([foo],[bar],[kin],[blat])
) AS p;

 

Results for dynamic PIVOT

This is a fairly trivial example, but I hope it demonstrates one approach you could use to achieve dynamic PIVOT.

 

 

댓글 남기기 응답 취소

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.

다음의 HTML 태그와 속성을 사용할 수 있습니다: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

그 밖의 기능

  • 등록하기
  • 로그인
  • 글 RSS
  • 댓글 RSS
  • WordPress.org

Service Title #1

Nullam dignissim convallis est. In hac habitasse platea dictumst. Ut aut reiciendis voluptatibus, tortor!

Service Title #2

Nullam dignissim convallis est. In hac habitasse platea dictumst. Ut aut reiciendis voluptatibus, tortor!

Service Title #3

Nullam dignissim convallis est. In hac habitasse platea dictumst. Ut aut reiciendis voluptatibus, tortor!

Service Title #4

Nullam dignissim convallis est. In hac habitasse platea dictumst. Ut aut reiciendis voluptatibus, tortor!

Copyright © 2025. All Rights Reserved. Powered by WordPress. Designed by MageeWP Themes