SQL行转列列转行
题目一:静态行转列和列转行
1.行转列
在电商或游戏报表中,通常需要将存在某列中的不同类别(如渠道、月份、品类)作为单独的列展示,以便于业务方直接阅读。
输入表:user_pay_table(用户支付记录)
date | paymethod | gmv |
20250301 | 支付宝 | 269 |
20250301 | 微信 | 194 |
20250301 | 银联 | 67 |
20250301 | ApplePay | 119 |
20250302 | 支付宝 | 49 |
20250302 | 微信 | 27 |
20250302 | 银联 | 32 |
20250302 | ApplePay | 19 |
期望输出:
date | 支付宝GMV | 微信GMV | 银联GMV | ApplePayGMV |
20250301 | 269 | 194 | 67 | 119 |
20250302 | 49 | 27 | 32 | 19 |
解题思路:
1.对date分组(GROUP BY),用 CASE WHEN(或 IF) 判断原表中的类别
2.配合聚合函数(SUM)计算每一类的和,将其转化为新的列名
注意NULL 处理:
形式一:ELSE 0
适用场景:财务报表、金额统计、计数。没有支付宝支付的日期,显示为 0
形式二:ELSE NULL,默认省略不写
适用场景:精细化分析、BI 展示、同比环比计算。没有数据的格子是 NULL。
SELECT
date,
SUM(CASE WHEN paymethod = '支付宝' THEN gmv ELSE 0 END) AS `支付宝GMV`,
SUM(CASE WHEN paymethod = '微信' THEN gmv ELSE 0 END) AS `微信GMV`,
SUM(CASE WHEN paymethod = '银联' THEN gmv ELSE 0 END) AS `银联GMV`,
SUM(CASE WHEN paymethod = 'ApplePay' THEN gmv ELSE 0 END) AS `ApplePayGMV`
FROM user_pay_table
GROUP BY date;
2.列转行
解题思路:
1.使用SELECT筛选出date和每一列,并加上常量标签
2.使用UNION ALL实现自连接,最后进行排序
SELECT date, '支付宝' AS paymethod, `支付宝GMV` AS gmv FROM pivot_result UNION ALL SELECT date, '微信', `微信GMV` FROM pivot_result UNION ALL SELECT date, '银联', `银联GMV` FROM pivot_result UNION ALL SELECT date, 'ApplePay', `ApplePayGMV` FROM pivot_result ORDER BY date, paymethod;
题目二:复杂列转行
在用户标签系统或推荐系统中,为了节省存储空间,经常会将多个属性拼接在同一个字段里(如 a_b_c)。但在进行分析时,需要将这些属性展开,以便与其他维度进行关联。
输入表:tableB
game | |
10000 | a_b_c |
20000 | c_d |
期望输出 (tableA):
game | |
10000 | a |
10000 | b |
10000 | c |
20000 | c |
20000 | d |
解题思路:
1.使用 SPLIT()函数将字符串按分隔符切割成数组
2.使用 EXPLODE()爆炸函数将数组中的每个元素变成单独的一行,与 LATERAL VIEW配合使用
SELECT
qq,
game_single AS game
FROM tableB
LATERAL VIEW explode(split(game, '_')) t AS game_single;

