2010-03-31 7 views
8

Ich habe eine Abfrage, wo ich Pivotzeile Werte in Spaltennamen ich versucht, und zur Zeit bin ich mit SUM(Case...) As 'ColumnName' Aussagen, etwa so:Dynamisches SQL zum Generieren von Spaltennamen?

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 

Die obige Abfrage funktioniert gut und gibt mir genau das, was ich brauche. Aber ich schreibe aus der SUM(Case... Aussagen von Hand auf der Grundlage der Ergebnisse der folgenden Abfrage:

Select Distinct Sku2 From OrderDetailDeliveryReview 

Gibt es eine Möglichkeit, T-SQL innerhalb einer gespeicherten Prozedur verwenden, dass ich dynamisch die SUM(Case... Aussagen generieren von der Select Distinct Sku2 From OrderDetailDeliveryReview Abfrage und führen Sie dann den resultierenden SQL-Code aus?

Antwort

10

eine Menge von diesen im Laufe der Jahre beantwortet Nachdem durch die Generierung dynamischer Dreh SQL aus den Metadaten, haben einen Blick auf diese Beispiele:

SQL Dynamic Pivot - how to order columns

SQL Server 2005 Pivot on Unknown Number of Columns

What SQL query or view will show "dynamic columns"

How do I Pivot on an XML column's attributes in T-SQL

How to apply the DRY principle to SQL Statements that Pivot Months

In Ihrem speziellen Fall (den ANSI-Pivot anstelle von SQL Server 2005 der PIVOT-Funktion):

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) 
+0

Danke für Ihre Antwort. Ich habe viele Antworten gesehen, die 'COALESCE' verwenden, aber was genau macht diese Funktion? –

+0

Wenn ich versuche, Ihre Abfrage unverändert auszuführen, erhalte ich eine Fehlermeldung in Zeile 15: "Falsche Syntax in der Nähe des Schlüsselwortes 'FROM'." Wenn ich das Komma am Ende von Zeile 14 entferne, erhalte ich eine Fehlermeldung in * Zeile 3 *, die besagt: "Falsche Syntax in der Nähe von 'SUMME'" Irgendwelche Ideen, was hier vor sich geht oder wie das zu debuggen ist? –

+0

@Cade Roux Ok, ich habe den Code optimiert (setze das Komma in die Anführungszeichen am Ende von Zeile 14; fügte eine Zeile hinzu, um das Komma von @column_list zu trimmen).Jetzt funktioniert es, was großartig ist, aber ich kann nicht herausfinden, was zwischen den Zeilen 14 und 17 passiert. –

2

Ich weiß, dass SO Suchmaschine nicht perfekt ist, aber Ihre Frage wurde in SQL Server PIVOT Column Data beantwortet.
Siehe auch Creating cross tab queries and pivot tables in SQL.

+0

@van fand ich heraus, dass meine Programmierung Abfragen wie folgt durch das Vorsetzen, 'Stackoverflow SQL Server Pivot', ich Bing bekommen die Website gut (obwohl die„andere“Legacy-Motor gut: D auch) –

+0

FYI für alle, die nicht wissen: Ich verwende in der Regel Google: "site: stackoverflow.com sql Server dynamische pivot cade roux", um alle meine früheren Antworten zu diesem (oder einem beliebigen) Thema zu finden. –

1

Warum dies mit harten codierten Spaltennamen, wenn Sie das alles aus einer Tabelle dynamisch ziehen kann?

Mit UNPIVOT und COALESCE kann ich dynamisch eine Liste von Spalten aus beliebigen Tabellen und zugeordneten Spaltenwerten für jeden Datensatz in einer Datensatzliste ziehen und sie in einer Liste von Spaltennamen mit Werten nach Zeile kombinieren. Hier ist der Code. Geben Sie einfach Ihren Datenbank- und Tabellennamen ein. Die Spalten-/Wertetabelle wird für Sie in SQL Server erstellt. Denken Sie daran, eine gemeinsame Spalte mit Werten für die Spalten zu erhalten, die Sie in SQL-Varianten oder Textzeichenfolgen konvertieren möchten. Aber eine gute Möglichkeit, eine Beispielspaltenliste von Werten mit übereinstimmenden Spaltennamen und -typen mit unseren while-Schleifen oder Cursors zu erhalten. Es ist ziemlich schnell:

-- First get a list of all known columns in your database, dynamically... 
DECLARE @COLUMNS nvarchar(max) 
SELECT @COLUMNS = 

CASE 
WHEN A.DATA_TYPE = 'nvarchar' OR A.DATA_TYPE = 'ntext' THEN 
COALESCE(@COLUMNS + ',','') + 'CAST(CONVERT(nvarchar(4000),['+A.[name]+']) AS sql_variant) AS ['+A.[name]+']' 
WHEN A.DATA_TYPE = 'datetime' OR A.DATA_TYPE = 'smalldatetime' THEN 
COALESCE(@COLUMNS + ',','') + 'CAST(CONVERT(nvarchar,['+A.[name]+'],101) AS sql_variant) AS ['+A.[name]+']' 
ELSE 
COALESCE(@COLUMNS + ',','') + 'CAST(['+A.[name]+'] AS sql_variant) AS ['+A.[name]+']' 
END 

FROM 
(
SELECT 
A.name, 
C.DATA_TYPE 
FROM YOURDATABASENAME.dbo.syscolumns A 
INNER JOIN YOURDATABASENAME.dbo.sysobjects B ON B.id = A.id 
LEFT JOIN 
(
SELECT 
COLUMN_NAME, 
DATA_TYPE 
FROM YOURDATABASENAME.INFORMATION_SCHEMA.COLUMNS 
WHERE TABLE_NAME = 'YOURTABLENAME' 
) C ON C.COLUMN_NAME = A.name 
WHERE B.name = 'YOURTABLENAME' 
AND C.DATA_TYPE <> 'timestamp' 
) A 
-- Test that the formatted columns list is returned... 
--SELECT @COLUMNS 

-- This gets a second string list of all known columns in your database, dynamically... 
DECLARE @COLUMNS2 nvarchar(max) 
SELECT @COLUMNS2 = COALESCE(@COLUMNS2 + ',','') + '['+A.[name]+']' 
FROM 
(
SELECT 
A.name, 
C.DATA_TYPE 
FROM YOURDATABASENAME.dbo.syscolumns A 
INNER JOIN YOURDATABASENAME.dbo.sysobjects B ON B.id = A.id 
LEFT JOIN 
(
SELECT 
COLUMN_NAME, 
DATA_TYPE 
FROM YOURDATABASENAME.INFORMATION_SCHEMA.COLUMNS 
WHERE TABLE_NAME = 'YOURTABLENAME' 
) C ON C.COLUMN_NAME = A.name 
WHERE B.name = 'YOURTABLENAME' 
AND C.DATA_TYPE <> 'timestamp' 
) A 
-- Test that the formatted columns list is returned... 
--SELECT @COLUMNS2 


-- Now plug in the list of the dynamic columns list into an UNPIVOT to get a Column Name/Column Value list table... 
DECLARE @sql nvarchar(max) 
SET @sql = 
' 
SELECT 
ColumnName,ColumnValue 
FROM 
(
SELECT 
'[email protected]+' 
FROM YOURDATABASENAME.dbo.YOURTABLENAME 
WHERE CHANGE_ID IN (SELECT ChangeId FROM YOURDATABASENAME.dbo.OperatorProcess WHERE OperatorProcessID = 3) 
) AS SourceTable 
UNPIVOT 
(
ColumnValue FOR ColumnName IN ('[email protected]+') 
) AS PivotTable 
' 

EXEC (@sql) 
+0

Zeile 9 führt zu einem Fehler: "Ungültiger Spaltenname 'CHANGE_ID'." – JESii

0
-- Darshankar Madhusudan i can do dynamic columnheading table easly... 
--thanks 
declare @incr int = 1, 
     @col int, 
     @str varchar(max), 
     @tblcrt varchar(max), 
     @insrt varchar(max), 
     set @tblcrt = 'DECLARE @Results table ('   
     set @str = ''  
     set @insrt = '' 
    select @col = max(column_id) From tempdb.sys.all_columns where object_id = object_id('tempdb.dbo.#aaa') 
    while @incr <= @col 
     BEGIN 
      SELECT @STR = @STR +case when @incr = 1 then '''' else ',''' end +rtrim(ltrim(NAME))+'''' FROM TEMPDB.SYS.ALL_COLUMNS WHERE OBJECT_ID = OBJECT_ID('TEMPDB.DBO.#AAA') and column_id = @incr 
      set @tblcrt = @tblcrt + case when @incr = 1 then '' else ',' end + 'Fld'+CAST(@incr as varchar(3)) +' varchar(50)' 
      set @insrt = @insrt + case when @incr = 1 then '' else ',' end + 'Fld'+CAST(@incr as varchar(3)) 
      SET @INCR = @INCR + 1 
     END 
     set @tblcrt = @tblcrt + ')' 
     set @insrt = 'insert into @Results('[email protected]+') values (' + @STR +')' 
     set @tblcrt = @tblcrt+ ';' + @insrt + 'select * from @Results ' 
exec(@tblcrt)