0%

hive中没有group_concat

hive实现分组拼接功能:替代 MySQL 的 group_concat

在 MySQL 中,group_concat 用于将分组后的多行数据按指定分隔符拼接,而 Hive 中虽无此函数,但可通过 collect_set/collect_list + concat_ws 的组合实现相同功能。本文详细介绍这一替代方案的原理、用法及注意事项。

核心函数解析

实现分组拼接需用到两个核心函数,二者配合可完成 “分组聚合 → 拼接字符串” 的全流程:

collect_set(col) / collect_list(col)

  • 功能:将分组内某列的所有值聚合为一个数组。

  • 区别

    • collect_set:去重,返回无重复元素的数组;
    • collect_list:不去重,保留所有元素(包括重复值)。
  • 示例

    若分组后某列值为[‘a’, ‘b’, ‘a’],则:

    • collect_set(col) 返回 ['a', 'b']
    • collect_list(col) 返回 ['a', 'b', 'a']

concat_ws(separator, array)

  • 功能:将数组中的元素按指定分隔符(separator)拼接为字符串。
  • 参数
    • separator:分隔符(如 ',''|');
    • array:数组(通常为 collect_setcollect_list 的输出)。
  • 示例
    concat_ws(',', ['a', 'b']) 返回 'a,b'

完整替代方案:分组拼接实现

基本语法

1
2
3
4
5
SELECT  
分组列,
concat_ws('分隔符', collect_set(待拼接列)) AS 拼接结果列
FROM 表名
GROUP BY 分组列;

实例解析

需求是 “按 doc_id 分组,拼接对应的 name 字段,用逗号分隔”:

1
2
3
4
5
6
SELECT  
dcm.doc_id AS doc_id,
concat_ws(',', collect_set(cate.NAME)) AS name -- 去重拼接
FROM dcm
LEFT JOIN cate ON cate.id = dcm.categories_id
GROUP BY dcm.doc_id;
执行逻辑:
  1. GROUP BY dcm.doc_id:按 doc_id 分组;
  2. collect_set(cate.NAME):在每个分组内收集 name 值并去重,生成数组;
  3. concat_ws(',', ...):将数组元素用逗号拼接为字符串,如 '分类1,分类2'

保留重复值的场景

若需保留重复的 name(如同一 doc_id 对应多个相同 name 需全部显示),改用 collect_list

1
2
3
4
5
6
SELECT  
dcm.doc_id AS doc_id,
concat_ws(',', collect_list(cate.NAME)) AS name -- 不去重拼接
FROM dcm
LEFT JOIN cate ON cate.id = dcm.categories_id
GROUP BY dcm.doc_id;

进阶用法与注意事项

1. 多列拼接

若需拼接多个字段(如 nameid),可先通过 concat 合并列,再聚合拼接:

1
2
3
4
5
SELECT  
doc_id,
concat_ws(';', collect_set(concat(name, ':', id))) AS name_id -- 格式:name:id;name2:id2
FROM 表名
GROUP BY doc_id;

2. 排序后拼接

Hive 中 collect_set/collect_list 不保证元素顺序,若需按特定规则排序(如按 name 字母序),需结合 sort_array

1
2
3
4
5
SELECT  
doc_id,
concat_ws(',', sort_array(collect_set(name))) AS sorted_name -- 先排序再拼接
FROM 表名
GROUP BY doc_id;

3. 注意事项

  • 性能问题collect_set/collect_list 会将分组内所有数据加载到内存,若分组数据量过大(如百万级),可能导致 OOM,需谨慎使用。
  • NULL 值处理:若待拼接列含 NULLcollect_set 会自动忽略 NULLconcat_ws 也会跳过 NULL,无需额外处理。
  • 分隔符选择:避免使用待拼接列中已存在的字符作为分隔符(如列值含逗号则改用 |;),否则后续解析会出错。

与 MySQL group_concat 的对比

功能 MySQL group_concat Hive 替代方案
去重 需要加 DISTINCT(如 group_concat(DISTINCT name) collect_set 自动去重
不去重 默认不去重 collect_list 保留重复值
排序 支持 ORDER BY(如 group_concat(name ORDER BY id) 需嵌套 sort_array
性能 适合小数据量分组 大数据量需注意内存开销

欢迎关注我的其它发布渠道