Bu sorunun daha eski olduğunu biliyorum ama cevapları arıyordum ve sorunun "dinamik" kısmını genişletebileceğimi ve muhtemelen birine yardım edebileceğimi düşündüm.
Her şeyden önce, bu çözümü birkaç iş arkadaşının hızlı bir şekilde döndürülmesi gereken tutarsız ve büyük veri kümeleriyle yaşadıkları bir sorunu çözmek için inşa ettim.
Bu çözüm, saklı bir yordamın oluşturulmasını gerektirir, bu yüzden ihtiyaçlarınız için söz konusu değilse, lütfen şimdi okumayı bırakın.
Bu yordam, değişken tablolar, sütun adları ve toplamalar için dinamik olarak pivot ifadeleri oluşturmak üzere bir pivot ifadesinin temel değişkenlerini alacaktır. Statik sütun, pivot için grup kimliği / kimlik sütunu olarak kullanılır (bu gerekli değilse koddan çıkarılabilir, ancak pivot ifadelerinde oldukça yaygındır ve orijinal sorunu çözmek için gereklidir), pivot sütunu sonuçta elde edilen sütun adlarından üretilecek ve değer sütunu toplamın uygulanacağı değerdir. Table parametresi, şema (schema.tablename) içeren tablonun adıdır, kodun bu kısmı, olmasını istediğim kadar temiz olmadığı için biraz sevgi kullanabilir. Benim için çalıştı çünkü benim kullanım kamuya açık değildi ve sql enjeksiyon bir endişe değildi.
Saklı yordamı oluşturmak için kod ile başlayalım. Bu kod SSMS 2005 ve sonraki tüm sürümlerinde çalışmalıdır, ancak 2005 veya 2016'da test etmedim, ancak neden işe yaramadığını göremiyorum.
create PROCEDURE [dbo].[USP_DYNAMIC_PIVOT]
(
@STATIC_COLUMN VARCHAR(255),
@PIVOT_COLUMN VARCHAR(255),
@VALUE_COLUMN VARCHAR(255),
@TABLE VARCHAR(255),
@AGGREGATE VARCHAR(20) = null
)
AS
BEGIN
SET NOCOUNT ON;
declare @AVAIABLE_TO_PIVOT NVARCHAR(MAX),
@SQLSTRING NVARCHAR(MAX),
@PIVOT_SQL_STRING NVARCHAR(MAX),
@TEMPVARCOLUMNS NVARCHAR(MAX),
@TABLESQL NVARCHAR(MAX)
if isnull(@AGGREGATE,'') = ''
begin
SET @AGGREGATE = 'MAX'
end
SET @PIVOT_SQL_STRING = 'SELECT top 1 STUFF((SELECT distinct '', '' + CAST(''[''+CONVERT(VARCHAR,'+ @PIVOT_COLUMN+')+'']'' AS VARCHAR(50)) [text()]
FROM '+@TABLE+'
WHERE ISNULL('+@PIVOT_COLUMN+','''') <> ''''
FOR XML PATH(''''), TYPE)
.value(''.'',''NVARCHAR(MAX)''),1,2,'' '') as PIVOT_VALUES
from '+@TABLE+' ma
ORDER BY ' + @PIVOT_COLUMN + ''
declare @TAB AS TABLE(COL NVARCHAR(MAX) )
INSERT INTO @TAB EXEC SP_EXECUTESQL @PIVOT_SQL_STRING, @AVAIABLE_TO_PIVOT
SET @AVAIABLE_TO_PIVOT = (SELECT * FROM @TAB)
SET @TEMPVARCOLUMNS = (SELECT replace(@AVAIABLE_TO_PIVOT,',',' nvarchar(255) null,') + ' nvarchar(255) null')
SET @SQLSTRING = 'DECLARE @RETURN_TABLE TABLE ('+@STATIC_COLUMN+' NVARCHAR(255) NULL,'+@TEMPVARCOLUMNS+')
INSERT INTO @RETURN_TABLE('+@STATIC_COLUMN+','+@AVAIABLE_TO_PIVOT+')
select * from (
SELECT ' + @STATIC_COLUMN + ' , ' + @PIVOT_COLUMN + ', ' + @VALUE_COLUMN + ' FROM '+@TABLE+' ) a
PIVOT
(
'+@AGGREGATE+'('+@VALUE_COLUMN+')
FOR '+@PIVOT_COLUMN+' IN ('+@AVAIABLE_TO_PIVOT+')
) piv
SELECT * FROM @RETURN_TABLE'
EXEC SP_EXECUTESQL @SQLSTRING
END
Sonra verilerimizi örnek için hazırlayacağız. Toplam değişikliğin çeşitli çıktılarını göstermek için bu kavram kanıtında kullanılacak birkaç veri öğesinin eklenmesiyle veri yanıtını kabul edilen cevaptan aldım.
create table temp
(
date datetime,
category varchar(3),
amount money
)
insert into temp values ('1/1/2012', 'ABC', 1000.00)
insert into temp values ('1/1/2012', 'ABC', 2000.00) -- added
insert into temp values ('2/1/2012', 'DEF', 500.00)
insert into temp values ('2/1/2012', 'DEF', 1500.00) -- added
insert into temp values ('2/1/2012', 'GHI', 800.00)
insert into temp values ('2/10/2012', 'DEF', 700.00)
insert into temp values ('2/10/2012', 'DEF', 800.00) -- addded
insert into temp values ('3/1/2012', 'ABC', 1100.00)
Aşağıdaki örnekler, çeşitli toplamaları basit bir örnek olarak gösteren çeşitli yürütme ifadelerini göstermektedir. Örneği basit tutmak için statik, pivot ve değer sütunlarını değiştirmeyi tercih etmedim. Kendinizle uğraşmaya başlamak için kodu kopyalayıp yapıştırabilmeniz gerekir
exec [dbo].[USP_DYNAMIC_PIVOT] 'date','category','amount','dbo.temp','sum'
exec [dbo].[USP_DYNAMIC_PIVOT] 'date','category','amount','dbo.temp','max'
exec [dbo].[USP_DYNAMIC_PIVOT] 'date','category','amount','dbo.temp','avg'
exec [dbo].[USP_DYNAMIC_PIVOT] 'date','category','amount','dbo.temp','min'
Bu yürütme, sırasıyla aşağıdaki veri kümelerini döndürür.