前几天我在StackOverflow(stackoverflow.com/questions/4663698/how-can-i-display-a-consolidated-version-of-my-sql-server-table)中打开了一个主题。那时我需要有关如何在数据透视表上显示数据的帮助。从我在论坛中获得的帮助,我的研究使我进入了关于动态SQL的页面:www.sommarskog.se/dynamic_sql.html。然后它引导我使用Itzik Ben-Gan创建的这个令人敬畏的SQL脚本,它将创建一个存储过程,完全按照我想要的方式输出数据透视表:sommarskog.se/pivot_sp.sp。
好吧,差不多。我需要在此存储过程中进行一处更改。我没有从SPROC中的@on_cols变量中提取动态列名,而是需要输出表以简单的ASC顺序保存通用列名。可能是,例如,col1,col2,col3,col4 ......动态列名称对我来说是个问题。所以我需要按照它们出现的顺序用它们的索引命名。我已经尝试过各种改变这个伟大的SQL脚本的东西,但是它不起作用。我没有粘贴代码中的代码,因为它太长了,但链接above会让我们在那里。
任何帮助表示赞赏。非常感谢你
答案 0 :(得分:1)
您需要此辅助函数或类似的东西将分隔列表(列名称)拆分为行
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 proc更改为以下内容 (SQL Server支持多行字符串,因此我删除了所有“+ @newline +”s)
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