行の値を列名にピボットしようとしているクエリがあり、現在は次のようにSUM(Case...) As 'ColumnName'
ステートメントを使用しています。
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
上記のクエリはうまく機能し、必要なものを正確に提供してくれます。ただし、次のクエリの結果に基づいて、SUM(Case...
ステートメントを手動で書き出しています。
Select Distinct Sku2 From OrderDetailDeliveryReview
ストアドプロシージャ内でT-SQLを使用して、SUM(Case...
クエリからSelect Distinct Sku2 From OrderDetailDeliveryReview
ステートメントを動的に生成し、結果のSQLコードを実行する方法はありますか?
メタデータから動的ピボットSQLを生成することにより、長年にわたってこれらの多くに答えてきたので、次の例を見てください。
DRY原則を月をピボットするSQLステートメントに適用する方法
特定の場合(SQL Server 2005のPIVOT機能の代わりにANSIピボットを使用):
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)
SO検索エンジンは完璧ではありませんが、あなたの質問は SQL Server PIVOT列データ で回答されています。
SQLでのクロスタブクエリとピボットテーブルの作成 も参照してください。
これらすべてを任意のテーブルから動的にプルできるのに、ハードコードされた列名を使用するのはなぜですか?
UNPIVOTとCOALESCEを使用すると、任意のテーブルから列のリストを動的にプルし、レコードリスト内の任意のレコードに関連付けられた列の値を取得して、列名のリストと行ごとの値を組み合わせることができます。これがコードです。データベースとテーブル名をドロップするだけです。列/値テーブルはSQLServerで生成されます。 SQLバリアントまたはテキスト文字列に変換する列の値の共有列を取得することを覚えておいてください。しかし、whileループまたはカーソルを使用して、列名とタイプが一致する値のサンプル列リストを取得するための優れた方法です。そのかなり速い:
-- 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
'+@COLUMNS+'
FROM YOURDATABASENAME.dbo.YOURTABLENAME
WHERE CHANGE_ID IN (SELECT ChangeId FROM YOURDATABASENAME.dbo.OperatorProcess WHERE OperatorProcessID = 3)
) AS SourceTable
UNPIVOT
(
ColumnValue FOR ColumnName IN ('+@COLUMNS2+')
) AS PivotTable
'
EXEC (@sql)
-- 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('+@insrt+') values (' + @STR +')'
set @tblcrt = @tblcrt+ ';' + @insrt + 'select * from @Results '
exec(@tblcrt)