在 Hive SQL 中,行转列和列转行是常见的数据转换操作。以下是详细说明和示例:
一、行转列(多行转多列)
场景:将同一分组下的多行数据合并为单行,不同值转为新列(如学生各科成绩横向展示)。
数据示例 (student_scores
):
student_id | subject | score |
---|
1 | Math | 90 |
1 | English | 85 |
2 | Math | 92 |
目标(每个学生一行,科目成绩转为列):
student_id | Math | English |
---|
1 | 90 | 85 |
2 | 92 | NULL |
SQL 实现:
SELECT
student_id,
MAX(CASE WHEN subject = 'Math' THEN score END) AS Math,
MAX(CASE WHEN subject = 'English' THEN score END) AS English
FROM student_scores
GROUP BY student_id;
关键点:
- 使用
CASE WHEN
按条件生成新列 - 用聚合函数(如
MAX
/MIN
/SUM
)确保单行输出 - 必须配合
GROUP BY
分组字段
二、列转行(多列转多行)
场景:将单行的多列数据拆分为多行(如将横向科目成绩转为纵向记录)。
数据示例 (student_scores_wide
):
student_id | Math | English |
---|
1 | 90 | 85 |
2 | 92 | NULL |
目标(恢复为行式存储):
student_id | subject | score |
---|
1 | Math | 90 |
1 | English | 85 |
2 | Math | 92 |
2 | English | NULL |
SQL 实现:
SELECT student_id, 'Math' AS subject, Math AS score
FROM student_scores_wide
UNION ALL
SELECT student_id, 'English' AS subject, English AS score
FROM student_scores_wide;
优化方案(使用 LATERAL VIEW explode()
,Hive 特有):
SELECT student_id, subject, score
FROM student_scores_wide
LATERAL VIEW explode(
map( -- 构建科目-分数的键值对
'Math', Math,
'English', English
)
) subjects AS subject, score;
关键点:
UNION ALL
适合列数量固定的场景LATERAL VIEW + explode(map)
动态处理多列- 注意处理
NULL
值(Hive 中 NULL
会正常保留)
三、高级用法:动态行列转换
当列名不固定时(如新增科目),需结合 Hive 动态 SQL 或预处理:
- 行转列动态化:
使用 collect_list
+ 拼接字符串,再通过 UDF 解析(较复杂,通常需借助外部脚本生成 SQL)。 - 列转行动态化:
通过 Hive 元数据获取列名,动态生成 UNION ALL
语句(示例略,需依赖 Hive 变量或编程接口)。
总结对比
操作 | 核心方法 | 适用场景 |
---|
行转列 | CASE WHEN + 聚合函数 + GROUP BY | 固定列名,聚合统计 |
列转行 | UNION ALL 或 LATERAL VIEW explode | 列数量少或需动态处理 |
提示:Hive 3.0+ 支持 LATERAL VIEW inline(array_of_structs)
,但需先构造结构体数组。实际使用时请根据数据规模和复杂度选择合适方案。