views:

732

answers:

2

I have a query where I'm trying pivot row values into column names and currently I'm using SUM(Case...) As 'ColumnName' statements, like so:

SELECT
SKU1,
SUM(Case When Sku2=157 Then Quantity Else 0 End) As '157',
SUM(Case When Sku2=158 Then Quantity Else 0 End) As '158',
SUM(Case When Sku2=167 Then Quantity Else 0 End) As '167'
FROM
OrderDetailDeliveryReview
Group By
OrderShipToID,
DeliveryDate,
SKU1 

The above query works great and gives me exactly what I need. However, I'm writing out the SUM(Case... statements by hand based on the results of the following query:

Select Distinct Sku2 From OrderDetailDeliveryReview 

Is there a way, using T-SQL inside a stored procedure, that I can dynamically generate the SUM(Case... statements from the Select Distinct Sku2 From OrderDetailDeliveryReview query and then execute the resulting SQL code?

+2  A: 

I know that SO search engine is not perfect, but your question has been answered in SQL Server PIVOT Column Data.
Also see Creating cross tab queries and pivot tables in SQL.

van
@van i found out that by prefixing my programming queries like this, `StackOverflow SQL Server Pivot`, I get to Bing the site well (although the "other" legacy engine is good :D too)
Raj More
FYI for anyone who doesn't know: I typically use Google: "site:stackoverflow.com sql server dynamic pivot cade roux" to find all my previous answers on this (or any) topic.
Cade Roux
+2  A: 

Having answered a lot of these over the years by generating dynamic pivot SQL from the metadata, have a look at these examples:

http://stackoverflow.com/questions/1122117/sql-dynamic-pivot-how-to-order-columns

http://stackoverflow.com/questions/213702/sql-server-2005-pivot-on-unknown-number-of-columns

http://stackoverflow.com/questions/219559/what-sql-query-or-view-will-show-dynamic-columns

http://stackoverflow.com/questions/1580077/how-do-i-pivot-on-an-xml-columns-attributes-in-t-sql

http://stackoverflow.com/questions/463377/how-to-apply-the-dry-principle-to-sql-statements-that-pivot-months

In your particular case (using the ANSI pivot instead of SQL Server 2005's PIVOT feature):

DECLARE @template AS varchar(max)
SET @template = 'SELECT 
SKU1
{COLUMN_LIST}
FROM
OrderDetailDeliveryReview
Group By
OrderShipToID,
DeliveryDate,
SKU1
'

DECLARE @column_list AS varchar(max)
SELECT @column_list = COALESCE(@column_list, ',') + 'SUM(Case When Sku2=' + CONVERT(varchar, Sku2) + ' Then Quantity Else 0 End) As [' + CONVERT(varchar, Sku2) + '],' 
FROM OrderDetailDeliveryReview
GROUP BY Sku2
ORDER BY Sku2

Set @column_list = Left(@column_list,Len(@column_list)-1)

SET @template = REPLACE(@template, '{COLUMN_LIST}', @column_list)

EXEC (@template)
Cade Roux
Thanks for your answer. I've seen a lot of answers that use `COALESCE`, but what exactly is that function doing?
Ben McCormack
Also, If I try to run your query as-is, I get an error on Line 15: "Incorrect syntax near the keyword 'FROM'." If I remove the comma at the end of line 14, I then get an error message on *line 3* that says "Incorrect syntax near 'SUM'" Any ideas on what's going on here or how to debug this?
Ben McCormack
@Cade Roux Ok, I tweaked the code (put the comma within the quotes at the end of line 14; added a line to trim the comma off of @column_list). Now it works, which is great, but I can't figure out what's going on between lines 14 and 17.
Ben McCormack
@Ben McCormack Sorry for the typos. COALESCE(x, y, z) returns the first non-NULL argument. For two parameters, it's basically performing the same function as ISNULL(x, y) (but is more ANSI). The SELECT @var = @var + something from TABLE is a SQL Server quirky thing you can do which just keep appending to one variable to make the column list, which is then simply inserted in the template.
Cade Roux
@Cade Roux thanks again for your response. While I was trying to figure this out, I posted a new question to try to figure out what's going on with the variable assignment, but you may have answered it already: http://stackoverflow.com/questions/2555568/what-is-happening-in-this-t-sql-code
Ben McCormack