【SQL】常见SQL 行列转换的方法汇总 - 精华版
- 一、引言
- 二、SQL常见的行列转换对比
- 1. 行转列 Pivoting
- 1.1 CASE WHEN + 聚合函数
- 1.2 IF + 聚合函数
- 1.3 PIVOT操作符
- 2.列转行 Unpivoting
- 2.1 UNION ALL
- 2.2 EXPLODE函数(Hive/Spark)
- 2.3 UNPIVOT操作符
- 三、对比总结
- 四、总结建议
一、引言
- 近期参加了数据岗位的一些面试(如下图:近几年的面试数据),非常多的同学在简历上会写熟悉、精通SQL,但一旦进行原理性(对应数据开发岗)或者实操性(数据分析、数据产品岗)的沟通和测试,往往表现的不尽如人意。所以打算再开一个【SQL】的专栏,分享一些SQL的知识和技巧。
- SQL专题往期内容:
- 【SQL】基于多源SQL 去重方法对比 – 精华版
- 【SQL】常见SQL 行列转换的方法汇总 - 精华版

二、SQL常见的行列转换对比
1. 行转列 Pivoting
1.1 CASE WHEN + 聚合函数
- 实现方式:CASE条件判断生成新列,配合MAX/SUM等聚合函数处理数据。
- 优点:兼容性强,适用于所有支持SQL的数据库。
- 缺点:列固定时需手动编写大量条件,动态列处理困难。
SELECT name,MAX(CASE WHEN skill='语文' THEN 1 ELSE 0 END) AS is_chinese,MAX(CASE WHEN skill='数学' THEN 1 ELSE 0 END) AS is_math
FROM A
GROUP BY name;
| 姓名 | 是否语文 | 是否数学 |
| 张三 | 1 | 0 |
| 张三 | 0 | 1 |
| 姓名 | 是否语文 | 是否数学 |
| 张三 | 1 | 1 |
1.2 IF + 聚合函数
- 实现方式:类似CASE WHEN,但语法更简洁
- 优点:语法简化,适合少量固定列。
- 缺点:同case ,注意事项同case。
SELECT name,MAX(IF(course='语文', score, 0)) AS chinese
FROM A
GROUP BY name;
1.3 PIVOT操作符
- 实现方式:专用于行转列的语法,需指定聚合函数和转换列。
- 优点:语法简洁,逻辑清晰。
- 缺点:仅支持部分数据库(如SQL Server、Oracle),动态列需结合动态SQL。
SELECT * FROM Sales
PIVOT (SUM(Amount) FOR Month IN ([Jan-22], [Feb-22])) AS PivotTable;
2.列转行 Unpivoting
2.1 UNION ALL
- 实现方式:将多列拆分为多个SELECT子查询后合并。
- 优点:兼容性好,适用于所有数据库。
- 缺点:代码冗余,列多时维护困难。
SELECT name, '语文' AS subject, is_chinese AS value FROM A WHERE is_chinese = 1
UNION ALL
SELECT name, '数学' AS subject, is_math FROM B WHERE is_math = 1
2.2 EXPLODE函数(Hive/Spark)
- 实现方式:将数组或拆分后的字符串转换为多行。
- 优点:简洁高效,适合处理数组或分隔字符串。
- 缺点:仅适用于支持EXPLODE的大数据平台(如Hive)。
SELECT name, subject FROM B
LATERAL VIEW EXPLODE(SPLIT(subject, ',')) tmp AS subject;
2.3 UNPIVOT操作符
- 实现方式:专用于列转行的语法。
- 优点:语法直观,逻辑清晰。
- 缺点:仅支持部分数据库(如SQL Server)。
SELECT name, subject, value FROM A
UNPIVOT (value FOR subject IN (is_chinese, is_math)) AS UnpivotTable;
三、对比总结
方法 | 适用场景 | 优势 | 劣势 |
---|
CASE WHEN | 简单固定列的行转列 | 所有数据库支持,兼容性强 | 代码冗余,动态列处理困难 |
PIVOT/UNPIVOT | 支持该语法的数据库 | 语法简洁,逻辑清晰 | 动态列需结合动态SQL,兼容性差 |
UNION 系列 | 列转行且列数较少 | 所有数据库支持,简单通用 | 代码冗余,维护成本高 |
EXPLODE | 大数据平台中的数组或字符串拆分 | 高效简洁 | 环境受限,仅Hive/Spark等 |
四、总结建议
类型 | 优先级 |
---|
行转列 | PIVOT(若数据库支持) > CASE WHEN |
列转行 | UNPIVOT / EXPLODE > UNION ALL |
动态列处理 | 结合应用层逻辑生成SQL(如Java/Python拼接),或使用存储过程(偏应用场景,故这里不介绍) |
- 具体选择哪种类型实现,需要根据业务场景下,对应的数据库类型、数据量、列是否固定等等因素综合判断,从而选择相对较优的解。