So che questa domanda è più vecchia, ma stavo cercando le risposte e ho pensato che avrei potuto espandere la parte "dinamica" del problema e forse aiutare qualcuno.
Innanzitutto ho creato questa soluzione per risolvere un problema che un paio di colleghi stavano riscontrando con insistenti e grandi set di dati che dovevano essere girati rapidamente.
Questa soluzione richiede la creazione di una procedura memorizzata, quindi se è fuori questione per le tue esigenze, ti preghiamo di smettere di leggere ora.
Questa procedura prenderà in considerazione le variabili chiave di un'istruzione pivot per creare in modo dinamico istruzioni pivot per diverse tabelle, nomi di colonne e aggregati. La colonna Statica viene utilizzata come colonna gruppo / identità per il pivot (questo può essere rimosso dal codice se non necessario ma è abbastanza comune nelle istruzioni pivot ed era necessario per risolvere il problema originale), la colonna pivot è dove i nomi delle colonne risultanti dalla fine verranno generati e la colonna del valore è ciò a cui verrà applicato l'aggregato. Il parametro Table è il nome della tabella incluso lo schema (schema.tablename) questa parte del codice potrebbe usare un po 'd'amore perché non è così pulito come vorrei che fosse. Ha funzionato per me perché il mio utilizzo non era rivolto pubblicamente e l'iniezione sql non era un problema.
Iniziamo con il codice per creare la procedura memorizzata. Questo codice dovrebbe funzionare in tutte le versioni di SSMS 2005 e successive, ma non l'ho testato nel 2005 o nel 2016, ma non riesco a capire perché non funzionerebbe.
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
Successivamente prepareremo i nostri dati per l'esempio. Ho preso l'esempio di dati dalla risposta accettata con l'aggiunta di un paio di elementi di dati da utilizzare in questa dimostrazione del concetto per mostrare i vari risultati della modifica aggregata.
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)
I seguenti esempi mostrano le varie istruzioni di esecuzione che mostrano i vari aggregati come semplice esempio. Non ho scelto di cambiare le colonne statica, pivot e value per mantenere semplice l'esempio. Dovresti essere in grado di copiare e incollare il codice per iniziare a scherzare da solo
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'
Questa esecuzione restituisce rispettivamente i seguenti set di dati.