Hive中使用CASE语句结合GROUP BY报错,求正确实现方案
问题描述
原始数据:
| user_id | status | name |
|---|---|---|
| 11111 | active | John |
| 11111 | rejected | Jai |
| 22222 | active | Prince |
| 33333 | rejected | King |
期望输出:
| user_id | active_name | rejected_name |
|---|---|---|
| 11111 | John | Jai |
| 22222 | Prince | null |
| 33333 | null | King |
需求是按user_id聚合,根据status字段映射对应的name值。我写了下面的SQL但执行报错:
SELECT user_id, CASE WHEN status = 'active' THEN name ELSE NULL END AS active_name, CASE WHEN status = 'rejected' THEN name ELSE NULL END AS rejected_name FROM table GROUP BY user_id
请问有没有合适的实现方法?
解决方法
你写的SQL报错,核心原因是GROUP BY的聚合规则:非聚合列必须出现在GROUP BY子句里,但如果把status和name加进去,就没法按user_id单独聚合了。这里提供两种可行的实现方案:
方案一:聚合函数+CASE语句
用MAX()(或MIN(),因为每个user_id对应同一种status只会有一个有效name)包裹CASE表达式,就能正确聚合出每个user_id对应的两种状态名称:
SELECT user_id, MAX(CASE WHEN status = 'active' THEN name ELSE NULL END) AS active_name, MAX(CASE WHEN status = 'rejected' THEN name ELSE NULL END) AS rejected_name FROM your_table GROUP BY user_id;
逻辑是:对每个user_id,CASE会把对应状态的name保留,其他置为NULL,而MAX()会自动忽略NULL,提取出有效的名称值。
方案二:PIVOT列转行(适用于SQL Server、Oracle等支持的数据库)
如果你的数据库支持PIVOT语法,可以更简洁地实现列转行:
SELECT user_id, active AS active_name, rejected AS rejected_name FROM your_table PIVOT ( MAX(name) FOR status IN (active, rejected) ) AS pivot_table;
注意:记得把语句中的your_table替换成你的实际表名。
内容的提问来源于stack exchange,提问作者John Constantine
相关产品推荐
相关产品推荐

