Ich weiß, dass diese Frage älter ist, aber ich habe die Antworten durchgesehen und dachte, ich könnte den "dynamischen" Teil des Problems erweitern und möglicherweise jemandem helfen.
In erster Linie habe ich diese Lösung entwickelt, um ein Problem zu lösen, das einige Mitarbeiter mit inkonstanten und großen Datenmengen hatten, die schnell geschwenkt werden mussten.
Diese Lösung erfordert die Erstellung einer gespeicherten Prozedur. Wenn dies für Ihre Anforderungen nicht in Frage kommt, hören Sie jetzt bitte auf zu lesen.
Bei dieser Prozedur werden die Schlüsselvariablen einer Pivot-Anweisung berücksichtigt, um dynamisch Pivot-Anweisungen für verschiedene Tabellen, Spaltennamen und Aggregate zu erstellen. Die Spalte "Statisch" wird als Spalte "Gruppieren nach / Identität" für den Pivot verwendet (diese kann bei Bedarf aus dem Code entfernt werden, ist jedoch in Pivot-Anweisungen häufig anzutreffen und war zur Lösung des ursprünglichen Problems erforderlich) Die resultierenden Spaltennamen am Ende werden generiert, und auf die Wertespalte wird das Aggregat angewendet. Der Table-Parameter ist der Name der Tabelle, einschließlich des Schemas (schema.tabellenname). Dieser Teil des Codes könnte etwas Liebe gebrauchen, da er nicht so sauber ist, wie ich es gerne hätte. Es hat bei mir funktioniert, weil meine Nutzung nicht öffentlich zugänglich war und die SQL-Injektion kein Problem darstellte.
Beginnen wir mit dem Code zum Erstellen der gespeicherten Prozedur. Dieser Code sollte in allen Versionen von SSMS 2005 und höher funktionieren, aber ich habe ihn 2005 oder 2016 nicht getestet, kann aber nicht erkennen, warum er nicht funktionieren würde.
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
Als nächstes bereiten wir unsere Daten für das Beispiel vor. Ich habe das Datenbeispiel der akzeptierten Antwort mit einigen Datenelementen entnommen, die in diesem Proof of Concept verwendet werden sollen, um die unterschiedlichen Ergebnisse der aggregierten Änderung zu zeigen.
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)
Die folgenden Beispiele zeigen die verschiedenen Ausführungsanweisungen, die die verschiedenen Aggregate als einfaches Beispiel zeigen. Ich habe mich nicht dafür entschieden, die statischen, Pivot- und Wertespalten zu ändern, um das Beispiel einfach zu halten. Sie sollten in der Lage sein, den Code einfach zu kopieren und einzufügen, um selbst damit herumzuspielen
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'
Diese Ausführung gibt jeweils die folgenden Datensätze zurück.