如何在SQL Server中使用PIVOT实现指定格式的表格转换?
实现SQL表格的PIVOT转换(动态适配新增Code/Name)
静态PIVOT实现(针对现有固定Name值)
如果当前Name值固定为ABC、DEF、QWE,可以直接用静态PIVOT语句,同时通过ISNULL将缺失的Budget值转为0:
SELECT Code, ISNULL(ABC, 0) AS ABC, ISNULL(DEF, 0) AS DEF, ISNULL(QWE, 0) AS QWE FROM (SELECT Code, Name, Budget FROM BudgetTable) AS SourceTable PIVOT ( SUM(Budget) -- 因每个Code+Name组合唯一,SUM/MAX均可 FOR Name IN (ABC, DEF, QWE) ) AS PivotTable;
动态PIVOT实现(适配后续新增的Name值)
如果后续会新增更多Name或Code值,静态语句需要频繁修改,推荐用动态SQL自动生成列名:
SQL Server 2017+版本(支持STRING_AGG)
DECLARE @Columns NVARCHAR(MAX), @Query NVARCHAR(MAX); -- 自动获取所有不重复的Name并拼接为列名格式 SELECT @Columns = STRING_AGG(QUOTENAME(Name), ', ') FROM (SELECT DISTINCT Name FROM BudgetTable) AS Names; -- 生成动态PIVOT查询,自动处理NULL转0 SET @Query = N' SELECT Code, ' + STRING_AGG('ISNULL(' + QUOTENAME(Name) + ', 0) AS ' + QUOTENAME(Name), ', ') + ' FROM (SELECT Code, Name, Budget FROM BudgetTable) AS SourceTable PIVOT ( SUM(Budget) FOR Name IN (' + @Columns + ') ) AS PivotTable;'; -- 执行动态查询 EXEC sp_executesql @Query;
SQL Server 2016及以下版本(用STUFF+XML拼接)
如果你的SQL Server版本不支持STRING_AGG,可以用以下方式拼接列名:
DECLARE @Columns NVARCHAR(MAX), @IsNullColumns NVARCHAR(MAX), @Query NVARCHAR(MAX); -- 拼接PIVOT需要的列名 SELECT @Columns = STUFF((SELECT ', ' + QUOTENAME(Name) FROM (SELECT DISTINCT Name FROM BudgetTable) AS Names ORDER BY Name FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, ''); -- 拼接带ISNULL的列转换语句 SELECT @IsNullColumns = STUFF((SELECT ', ISNULL(' + QUOTENAME(Name) + ', 0) AS ' + QUOTENAME(Name) FROM (SELECT DISTINCT Name FROM BudgetTable) AS Names ORDER BY Name FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 2, ''); -- 生成并执行动态查询 SET @Query = N' SELECT Code, ' + @IsNullColumns + ' FROM (SELECT Code, Name, Budget FROM BudgetTable) AS SourceTable PIVOT ( SUM(Budget) FOR Name IN (' + @Columns + ') ) AS PivotTable;'; EXEC sp_executesql @Query;
说明
- 这里假设原始表名为
BudgetTable,你可以根据实际表名替换。 SUM(Budget)可以替换为MAX(Budget),因为每个Code+Name组合是唯一的,两种聚合函数结果一致。- 动态SQL会自动识别所有新增的Name值,无需手动修改查询语句。
内容的提问来源于stack exchange,提问作者Leonardo Abanto
相关产品推荐
相关产品推荐

