Saya tahu pertanyaan ini lebih lama tetapi saya mencari jawaban dan berpikir bahwa saya mungkin dapat memperluas bagian "dinamis" dari masalah dan mungkin membantu seseorang.
Pertama dan terpenting saya membangun solusi ini untuk memecahkan masalah yang dialami oleh beberapa rekan kerja dengan set data yang tidak konstan dan besar yang perlu diputar cepat.
Solusi ini memerlukan pembuatan prosedur tersimpan sehingga jika itu tidak sesuai dengan kebutuhan Anda, silakan berhenti membaca sekarang.
Prosedur ini akan mengambil variabel kunci dari pernyataan pivot untuk secara dinamis membuat pernyataan pivot untuk berbagai tabel, nama kolom, dan agregat. Kolom statis digunakan sebagai grup oleh / kolom identitas untuk pivot (ini dapat dihapus dari kode jika tidak diperlukan tetapi cukup umum dalam pernyataan pivot dan diperlukan untuk menyelesaikan masalah asli), kolom pivot adalah tempat nama kolom hasil akhir akan dihasilkan dari, dan kolom nilai adalah apa yang akan diterapkan pada agregat. Parameter Tabel adalah nama tabel termasuk skema (schema.tablename), bagian kode ini dapat menggunakan beberapa cinta karena tidak sebersih yang saya inginkan. Ini bekerja untuk saya karena penggunaan saya tidak menghadap ke publik dan injeksi sql bukan masalah.
Mari kita mulai dengan kode untuk membuat prosedur tersimpan. Kode ini harus bekerja di semua versi SSMS 2005 dan di atas tetapi saya belum mengujinya pada 2005 atau 2016 tetapi saya tidak bisa melihat mengapa itu tidak berhasil.
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
Selanjutnya kita akan mendapatkan data kita siap untuk contoh. Saya telah mengambil contoh data dari jawaban yang diterima dengan penambahan beberapa elemen data untuk digunakan dalam bukti konsep ini untuk menunjukkan hasil yang bervariasi dari perubahan agregat.
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)
Contoh-contoh berikut menunjukkan pernyataan eksekusi bervariasi yang menunjukkan agregat bervariasi sebagai contoh sederhana. Saya tidak memilih untuk mengubah kolom statis, pivot, dan nilai untuk menjaga contoh sederhana. Anda dapat menyalin dan menempelkan kode untuk mulai mengacaukannya sendiri
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'
Eksekusi ini mengembalikan set data berikut masing-masing.