2010-03-31 30 views
8

Mam kwerendy, gdzie próbuję wartości wierszy przestawnych do nazwy kolumn, a obecnie używam SUM(Case...) As 'ColumnName' sprawozdań, tak:Dynamiczny SQL do generowania nazw kolumn?

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 

Powyższa kwerenda działa doskonale i daje mi dokładnie to, czego potrzebuję. Jednak jestem wypisując SUM(Case... oświadczenia strony oparte na wynikach następujące zapytanie:

Select Distinct Sku2 From OrderDetailDeliveryReview 

Czy istnieje sposób, za pomocą T-SQL wewnątrz procedury przechowywanej, że mogę dynamicznego generowania sprawozdań SUM(Case... z zapytania Select Distinct Sku2 From OrderDetailDeliveryReview, a następnie wykonać wynikowy kod SQL?

Odpowiedz

10

Po odpowiedziało wiele z nich przez lata generowania dynamicznej obrotowy SQL z metadanych, rzucić okiem na tych przykładach:

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

w danym przypadku (używając pivot ANSI zamiast funkcji PIVOT SQL Server 2005 za):

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

Dzięki za odpowiedź. Widziałem wiele odpowiedzi, które używają 'COALESCE', ale co dokładnie robi ta funkcja? –

+0

Ponadto, jeśli spróbuję uruchomić zapytanie bez zmian, otrzymam komunikat o błędzie w wierszu 15: "Niepoprawna składnia w pobliżu słowa kluczowego" FROM "." Jeśli usunę przecinek na końcu wiersza 14, otrzymam komunikat o błędzie na * linii 3 *, który mówi "Niepoprawna składnia w pobliżu" SUM "" Jakieś pomysły na temat tego, co tu się dzieje lub jak to debugować? –

+0

@Cade Roux OK, poprawiłem kod (wstaw przecinek w cudzysłowie na końcu linii 14, dodano linię, aby przyciąć przecinek z @ column).Teraz działa, co jest świetne, ale nie wiem, co się dzieje między wierszami 14 i 17. –

2

Wiem, że wyszukiwarka SO nie jest idealna, ale na Twoje pytanie udzielono odpowiedzi pod numerem SQL Server PIVOT Column Data.
Zobacz także Creating cross tab queries and pivot tables in SQL.

+0

@van okazało się, że poprzedzając moje zapytania programowych tak, 'StackOverflow SQL Server Pivot', mogę Bing strona dobrze (choć„inne”jest silnik Legacy good: D too) –

+0

FYI dla każdego, kto nie wie: zazwyczaj korzystam z Google: "site: stackoverflow.com sql server dynamic pivot cade roux", aby znaleźć wszystkie moje poprzednie odpowiedzi na ten temat (lub dowolny temat). –

1

Dlaczego to za pomocą zakodowanego nazwy kolumn, gdy można wyciągnąć wszystko to dynamicznie z każdym stole?

Używając UNPIVOT i COALESCE, mogę dynamicznie wyciągnąć listę kolumn z dowolnej tabeli i powiązanych wartości kolumn dla dowolnego rekordu na liście rekordów i połączyć je na liście nazw kolumn z wartościami według wierszy. Oto kod. Po prostu wpisz swoją bazę danych i nazwę tabeli. Tabela kolumn/wartości zostanie wygenerowana dla ciebie w SQL Server. Pamiętaj, aby uzyskać udostępnioną kolumnę wartości dla kolumn, które chcesz przekonwertować na warianty sql lub ciągi tekstowe. Ale świetny sposób na uzyskanie przykładowej kolumny wartości z dopasowanymi nazwami i typami kolumn za pomocą naszych pętli while lub kursorów. Jego dość szybko:

-- 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

Wiersz 9 powoduje błąd: "Nieprawidłowa nazwa kolumny" 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) 
Powiązane problemy