Я знаю, що це питання старше, але я шукав відповіді і думав, що мені вдасться розширити "динамічну" частину проблеми і, можливо, допомогти комусь.
Перш за все, я створив це рішення, щоб вирішити проблему, яку мали декілька колег з непостійними та великими наборами даних, які потребують швидкого повороту.
Це рішення вимагає створення збереженої процедури, тому якщо це не викликає сумнівів для ваших потреб, будь ласка, перестаньте читати зараз.
У цій процедурі будуть взяті ключові змінні оператора зведення, щоб динамічно створювати зведені оператори для різних таблиць, назв стовпців та агрегатів. Стовпець Статичний використовується як стовпець групи по / ідентичності для повороту (це може бути викреслено з коду, якщо не потрібно, але досить поширене у зведених висловлюваннях і було необхідне для вирішення початкової проблеми), стовпчастий стовпчик - це місце імена кінцевих результатів будуть створені з, а стовпець значення - це те, до чого буде застосовано сукупність. Параметр Таблиця - це назва таблиці, включаючи схему (schema.tablename), що ця частина коду може використовувати деяку любов, оскільки вона не така чиста, як хотілося б. Це працювало для мене, оскільки моє використання не було загальнодоступним та введення sql не викликало проблем.
Почнемо з коду для створення збереженої процедури. Цей код повинен працювати у всіх версіях SSMS 2005 і вище, але я не тестував його в 2005 або 2016, але не можу зрозуміти, чому він не працює.
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
Далі ми підготуємо наші дані для прикладу. Я взяв приклад даних із прийнятої відповіді з додаванням декількох елементів даних для використання у цьому доказі концепції, щоб показати різноманітні результати сукупної зміни.
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)
Наступні приклади показують різноманітні оператори виконання, що показують різноманітні сукупності як простий приклад. Я не вирішив змінити стовпці статичних, зведених та значущих, щоб приклад був простим. Ви повинні мати можливість просто скопіювати і вставити код, щоб почати з ним возитися
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'
Це виконання повертає наступні набори даних відповідно.