hive中没有group_concat
Hive 分组拼接:collect_set + concat_ws,替代 MySQL 的 group_concat
在 MySQL 里,group_concat 是一个很常用的函数——按某个字段分组,把组内另一个字段的值用逗号拼成一行。
比如:
SELECT doc_id, GROUP_CONCAT(name) FROM table GROUP BY doc_id;
结果可能是:
doc_001 | 分类1,分类2,分类3
但 Hive 里没有 group_concat。
Hive 的替代方案是两步走:
collect_set/collect_list:把同组的多行聚合成一个数组concat_ws:把数组用分隔符拼成字符串
concat_ws(',', collect_set(列名)) -- 相当于 group_concat
两个函数的分工
| 函数 | 做什么 | 去重 |
|---|---|---|
collect_set(列) |
同组的多行聚合成一个数组 | 去重 |
collect_list(列) |
同组的多行聚合成一个数组 | 保留重复 |
concat_ws('分隔符', 数组) |
把数组元素拼成一个字符串 | — |
组合方式:
concat_ws(',', collect_set(列名)) -- 去重拼接
concat_ws(',', collect_list(列名)) -- 不去重拼接
一个实际的例子:文档的分类拼接
需求: 有一张文档分类关联表,一个文档可以属于多个分类。现在要按 doc_id 分组,把每个文档的所有分类名称拼成一行。
数据:
| doc_id | category_name | |
|---|---|---|
| doc_001 | 技术 | |
| doc_001 | 人工智能 | |
| doc_001 | 技术 | ← 重复了 |
| doc_002 | 设计 | |
| doc_002 | UI/UX |
SQL(去重拼接):
SELECT
doc_id,
concat_ws(',', collect_set(category_name)) AS categories
FROM doc_category
GROUP BY doc_id;
结果:
| doc_id | categories |
|---|---|
| doc_001 | 技术,人工智能 |
| doc_002 | 设计,UI/UX |
doc_001 里有三个分类,但”技术”出现了两次,collect_set 去重后只剩两个。
如果不去重(collect_list):
concat_ws(',', collect_list(category_name))
结果会变成:
| doc_id | categories |
|---|---|
| doc_001 | 技术,人工智能,技术 |
进阶:拼接多个字段
如果要拼接的是 name:id 这种格式:
SELECT
doc_id,
concat_ws(';', collect_set(concat(name, ':', id))) AS name_id_list
FROM table
GROUP BY doc_id;
结果:分类1:1;分类2:2;分类3:3
进阶:排序后再拼接
collect_set 和 collect_list 的顺序是不确定的。如果要按某个字段排序:
SELECT
doc_id,
concat_ws(',', sort_array(collect_set(name))) AS sorted_names
FROM table
GROUP BY doc_id;
sort_array 按字典序排序。如果需要自定义排序规则(比如按数字大小),用 sort_array(collect_set(name), false) 可改为降序。