如何将临时表列名查询结果转为列形式?求Pivot语法实现
解决临时表列名行转动态列的问题
首先得说,直接用普通的Pivot是搞不定的——因为Pivot要求你提前知道要转成的列名,而且必须配合聚合函数,而你现在连列名是什么都没法提前确定,所以必须靠动态SQL来实现,这也是这类未知列转行场景的标准解法。
下面分两种情况给你代码,适配不同版本的SQL Server:
情况1:SQL Server 2017及以上(支持STRING_AGG)
这个版本有个好用的STRING_AGG函数,能直接把列名拼接成我们需要的格式,代码如下:
DECLARE @cols NVARCHAR(MAX), @sql NVARCHAR(MAX); -- 第一步:把所有临时表的列名拼接成带引号的列表,用于后续Pivot和SELECT SELECT @cols = STRING_AGG(QUOTENAME(name), ', ') FROM tempdb.sys.columns WHERE object_id = OBJECT_ID('tempdb..##myTempTable'); -- 第二步:动态构建Pivot语句 SET @sql = N' SELECT ' + @cols + N' FROM ( -- 子查询里给每个列名加个固定分组ID,确保Pivot后只生成一行 SELECT name, name AS column_value, 1 AS group_id FROM tempdb.sys.columns WHERE object_id = OBJECT_ID(''tempdb..##myTempTable'') ) AS src PIVOT ( -- 用MAX做聚合,因为每个列名唯一,聚合结果就是列名本身 MAX(column_value) FOR name IN (' + @cols + N') ) AS pvt; '; -- 执行动态SQL EXEC sp_executesql @sql;
情况2:SQL Server 2016及以下(无STRING_AGG)
旧版本得用STUFF + FOR XML PATH来拼接列名,代码稍微麻烦一点,但原理一样:
DECLARE @cols NVARCHAR(MAX), @sql NVARCHAR(MAX); -- 用STUFF和XML PATH拼接列名列表 SELECT @cols = STUFF(( SELECT ', ' + QUOTENAME(name) FROM tempdb.sys.columns WHERE object_id = OBJECT_ID('tempdb..##myTempTable') ORDER BY name FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)'), 1, 2, ''); -- 同样构建动态Pivot语句 SET @sql = N' SELECT ' + @cols + N' FROM ( SELECT name, name AS column_value, 1 AS group_id FROM tempdb.sys.columns WHERE object_id = OBJECT_ID(''tempdb..##myTempTable'') ) AS src PIVOT ( MAX(column_value) FOR name IN (' + @cols + N') ) AS pvt; '; EXEC sp_executesql @sql;
关键点解释
- 动态SQL的必要性:因为列名未知,我们必须先从
tempdb.sys.columns里查询出所有列名,再把它们拼接到最终的SQL语句中。 - Pivot的聚合函数:这里用
MAX是因为每个列名在结果里只出现一次,聚合后就是它本身;你也可以用MIN,效果一样。 - QUOTENAME函数:用来处理列名包含空格、关键字(比如
SELECT)的情况,避免语法错误,非常重要。
执行完上面的代码,你就能得到一行数据,列就是临时表的所有列名,每个列的值就是对应的列名本身,完全符合你要的Col1 | Col2 | Col3 | ...的形式。
内容的提问来源于stack exchange,提问作者Patrick
相关产品推荐
相关产品推荐

