Вам нужна эта вспомогательная функция или что-то похожее для разделения списка с разделителями (имен столбцов) на строки
CREATE function dbo.values2table
(
@values varchar(max),
@separator varchar(3),
@limit int -- set to -1 for no limit
) returns @res table (id int identity, [value] varchar(max))
as
begin
declare @value varchar(50)
declare @commapos int, @lastpos int
set @commapos = 0
select @lastpos = @commapos, @commapos = charindex(@separator, @values, @lastpos+1)
while @commapos > @lastpos and @limit <> 0
begin
select @value = substring(@values, @lastpos+1, @commapos-@lastpos-1)
if @value <> '' begin
insert into @res select ltrim(rtrim(@value))
set @limit = @limit-1
end
select @lastpos = @commapos, @commapos = charindex(@separator, @values, @lastpos+1)
end
select @value = substring(@values, @lastpos+1, len(@values))
if @value <> '' insert into @res select ltrim(rtrim(@value))
return
end
GO
Затем измените процесс pivot_sp на следующий
(SQL Server поддерживает многострочные строки, поэтому я удалил все "+ @newline +")
CREATE PROC dbo.pivot_sp
@query AS NVARCHAR(MAX), -- The query, can also be the name of a table/view.
@on_rows AS NVARCHAR(MAX), -- The columns that will be regular rows.
@on_cols AS NVARCHAR(MAX), -- The columns that are to be pivoted.
@agg_func AS NVARCHAR(257) = N'MAX', -- Aggregate function.
@agg_col AS NVARCHAR(MAX), -- Column to aggregate.
@generic AS bit = 0,
@debug AS bit = 1
AS
-- Input validation
IF @query IS NULL OR @on_rows IS NULL OR @on_cols IS NULL
OR @agg_func IS NULL OR @agg_col IS NULL
BEGIN
RAISERROR('Invalid input parameters.', 16, 1);
RETURN;
END
-- Additional input validation goes here (SQL Injection attempts, etc.)
BEGIN TRY
DECLARE
@sql AS NVARCHAR(MAX),
@cols AS NVARCHAR(MAX),
@newline AS NVARCHAR(2);
SET @newline = NCHAR(13) + NCHAR(10);
-- If input is a valid table or view
-- construct a SELECT statement against it
IF COALESCE(OBJECT_ID(@query, N'U'),
OBJECT_ID(@query, N'V')) IS NOT NULL
SET @query = N'SELECT * FROM ' + @query;
-- Make the query a derived table
SET @query = N'(' + @query + N') AS Query';
-- Handle * input in @agg_col
IF @agg_col = N'*'
SET @agg_col = N'1';
-- Construct column list
SET @sql = N'
SET @result =
STUFF(
(SELECT N'','' + quotename(
CAST(pivot_col AS sysname)
) AS [text()]
FROM (SELECT DISTINCT '
+ @on_cols + N' AS pivot_col
FROM' + @query + N') AS DistinctCols
ORDER BY pivot_col
FOR XML PATH(''''))
,1, 1, N'''');'
IF @debug = 1
PRINT @sql
EXEC sp_executesql
@stmt = @sql,
@params = N'@result AS NVARCHAR(MAX) OUTPUT',
@result = @cols OUTPUT;
DECLARE @colsout nvarchar(max)
if @generic = 1
select @colsout = coalesce(@colsout,'') + value + '] as col'+right(id,10)
from dbo.values2table(left(@cols, LEN(@cols)-1), '],[', -1) X
else
select @colsout = @cols
-- Create the PIVOT query
SET @sql = N'
SELECT ' + @on_rows + ',' + @colsout + '
FROM (SELECT '
+ @on_rows
+ N', ' + @on_cols + N' AS pivot_col'
+ N', ' + @agg_col + N' AS agg_col
FROM ' + @query + N')' +
+ N' AS PivotInput
PIVOT(' + @agg_func + N'(agg_col)
FOR pivot_col IN(' + @cols + N')) AS PivotOutput;'
IF @debug = 1
PRINT @sql
EXEC sp_executesql @sql;
END TRY
BEGIN CATCH
DECLARE
@error_message AS NVARCHAR(2047),
@error_severity AS INT,
@error_state AS INT;
SET @error_message = ERROR_MESSAGE();
SET @error_severity = ERROR_SEVERITY();
SET @error_state = ERROR_STATE();
RAISERROR(@error_message, @error_severity, @error_state);
RETURN;
END CATCH
GO
А вот пример, который вы должны запускать с любой базы данных SQL Server.
exec dbo.pivot_sp @query = '
select o.name object_name, c.system_type_id, c.name
from sys.columns c
inner join sys.objects o on o.object_id=c.object_id
where o.is_ms_shipped = 0',
@on_rows = 'object_name',
@on_cols = 'system_type_id',
@agg_func = N'COUNT', -- Aggregate function.
@agg_col = 'name',
@generic=1,
@debug=1