Je sais que cette question est plus ancienne mais je cherchais à travers les réponses et pensais que je pourrais être en mesure d'étendre la partie "dynamique" du problème et éventuellement aider quelqu'un.
Tout d'abord, j'ai conçu cette solution pour résoudre un problème que deux collègues rencontraient avec des ensembles de données inconstants et volumineux devant être pivotés rapidement.
Cette solution nécessite la création d'une procédure stockée, donc si cela est hors de question pour vos besoins, veuillez arrêter de lire maintenant.
Cette procédure va prendre les variables clés d'une instruction pivot pour créer dynamiquement des instructions pivot pour différents tableaux, noms de colonnes et agrégats. La colonne statique est utilisée comme colonne de regroupement par / identité pour le pivot (cela peut être supprimé du code si ce n'est pas nécessaire mais est assez courant dans les instructions pivot et était nécessaire pour résoudre le problème d'origine), la colonne pivot est l'endroit où le les noms de colonne résultants finaux seront générés à partir de, et la colonne de valeur sera celle à laquelle l'agrégat sera appliqué. Le paramètre Table est le nom de la table, y compris le schéma (schema.tablename), cette partie du code pourrait utiliser un peu d'amour car elle n'est pas aussi propre que je le souhaiterais. Cela a fonctionné pour moi car mon utilisation n'était pas publique et l'injection SQL n'était pas un problème.
Commençons par le code pour créer la procédure stockée. Ce code devrait fonctionner dans toutes les versions de SSMS 2005 et supérieur mais je ne l'ai pas testé en 2005 ou 2016 mais je ne vois pas pourquoi cela ne fonctionnerait pas.
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
Ensuite, nous préparerons nos données pour l'exemple. J'ai pris l'exemple de données de la réponse acceptée avec l'ajout de quelques éléments de données à utiliser dans cette preuve de concept pour montrer les sorties variées du changement global.
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)
Les exemples suivants montrent les instructions d'exécution variées montrant les agrégats variés comme exemple simple. Je n'ai pas choisi de modifier les colonnes statique, pivot et valeur pour garder l'exemple simple. Vous devriez pouvoir simplement copier et coller le code pour commencer à jouer avec lui-même
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'
Cette exécution renvoie respectivement les ensembles de données suivants.