使用PIVOT操作符是最简单的方式来实现行转列。例如,假设有销售数据表:SELECT * FROM (SELECT 年份, 月份, 销售额 FROM 销售表) AS SourceTable PIVOT (SUM(销售额) FOR 月份 IN ([1月],[2月],[3月])) AS PivotTable; 这行代码就能快速把月份行转成列,展示每个月的销售额。
静态PIVOT示例
在SQL Server中,行转列可以使用PIVOT关键字。基本语法是:SELECT * FROM (SELECT col1, col2, val FROM table) p PIVOT (聚合函数(val) FOR col2 IN ([val1],[val2])) AS pvt; 比如学生成绩表,行转列后每个科目变成一列,分数直接聚合显示。
动态PIVOT实现
如果列是动态的,需要用动态SQL构建PIVOT。DECLARE @cols NVARCHAR(MAX), @sql NVARCHAR(MAX); SELECT @cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(类别) FROM 表名 FOR XML PATH(''),TYPE).value('.','NVARCHAR(MAX)'),1,1,''); SET @sql = 'SELECT * FROM (SELECT ... ) p PIVOT (SUM(金额) FOR 类别 IN (' + @cols + ')) AS pvt'; EXEC sp_executesql @sql; 这样就能自动生成所有类别列。
UNPIVOT反向操作
列转行用UNPIVOT:SELECT * FROM (SELECT 年, 一月, 二月 FROM 表) AS Table1 UNPIVOT (销售额 FOR 月份 IN (一月, 二月)) AS UnpvtTable; 这适合把宽表变窄表,便于进一步处理。
使用CASE WHEN技巧
老版本SQL Server没PIVOT可以用CASE:SELECT 年份, SUM(CASE WHEN 月份='1月' THEN 销售额 ELSE 0 END) AS 一月, SUM(CASE WHEN 月份='2月' THEN 销售额 ELSE 0 END) AS 二月 FROM 销售表 GROUP BY 年份; 简单有效,兼容性好。
数据透视实际应用
在报表中,行转列让数据一目了然。比如部门销售汇总:用PIVOT把产品列转成列头,每个部门一行,销售额数值填充,轻松生成Excel-like透视表。
性能优化提示
行转列后加索引到源列,避免全表扫描。动态PIVOT用临时表存列名,提高执行速度。测试显示,PIVOT比多CASE快20%以上。
FAQ
Q: PIVOT支持哪些聚合函数?
A: 支持SUM、AVG、MAX、MIN等。
Q: 动态列怎么处理未知类别?
A: 用动态SQL生成列列表。
Q: CASE WHEN和PIVOT哪个更快?
A: PIVOT通常更快,尤其大数据。
Q: 如何处理NULL值?
A: PIVOT默认显示NULL,可用ISNULL替换0。