SQL行转列核心是将离散值作新列名并旋转数据,通用写法为CASE WHEN+GROUP BY聚合,SQL Server/Oracle支持PIVOT关键字,MySQL需用CASE WHEN模拟,动态列需应用层处理。

SQL 行转列(Pivot)的核心是把某一列的**离散值**作为新列名,将对应的数据“旋转”过去。不同数据库语法差异较大,但思路一致:先聚合(避免多行冲突),再按条件分组展开。
标准 SQL(通用写法:CASE WHEN + GROUP BY)
这是兼容性最强的方式,适用于 MySQL、PostgreSQL、SQL Server、Oracle 等所有主流数据库。
- 用 CASE WHEN 对目标列的每个值单独提取,生成新列表达式
- 配合 MAX()/SUM()/COUNT() 等聚合函数,确保每组只返回一个值
- 必须搭配 GROUP BY 原始分组字段(如用户ID、日期等)
示例:将订单表中按商品类别的销售额转为横向列
SELECT order_date, MAX(CASE WHEN category = '电子' THEN amount END) AS 电子, MAX(CASE WHEN category = '服装' THEN amount END) AS 服装, MAX(CASE WHEN category = '食品' THEN amount END) AS 食品 FROM orders GROUP BY order_date;
SQL Server / Oracle:使用内置 PIVOT 关键字
语法更简洁,但要求明确指定列名,且不支持动态列(列名需写死)。
一套面向小企业用户的企业网站程序!功能简单,操作简单。实现了小企业网站的很多实用的功能,如文章新闻模块、图片展示、产品列表以及小型的下载功能,还同时增加了邮件订阅等相应模块。公告,友情链接等这些通用功能本程序也同样都集成了!同时本程序引入了模块功能,只要在系统默认模板上创建模块,可以在任何一个语言环境(或任意风格)的适当位置进行使用!
- SQL Server 示例:
SELECT order_date, [电子], [服装], [食品] FROM ( SELECT order_date, category, amount FROM orders ) AS src PIVOT ( SUM(amount) FOR category IN ([电子], [服装], [食品]) ) AS pvt;
- Oracle 11g+ 支持类似语法,关键字相同,括号内列名用双引号(如 "电子")
MySQL 8.0+:窗口函数辅助 + GROUP BY(无原生 PIVOT)
MySQL 没有 PIVOT 关键字,仍推荐 CASE WHEN 方式。若需动态列(比如类别不固定),必须靠应用层拼接 SQL 或用存储过程模拟。
- 动态场景常见于报表系统,数据库本身无法自动推导列名
- 可先查出所有 category 值:SELECT DISTINCT category FROM orders,再由程序生成完整 SQL
注意事项与常见坑
行转列不是“魔法”,本质是分组聚合后的结构重排,容易出错的点包括:
- 忘记加聚合函数 → 报错或结果不全(尤其是多条同组记录时)
- GROUP BY 字段漏掉关键维度 → 数据合并错误
- NULL 值未处理 → 转换后列中出现大量 NULL,影响后续计算或展示
- 字符串列用于 pivot 时未加引号或转义 → 语法错误(尤其在动态 SQL 中)









