一文说清楚Hive中常用的聚合函数[collect_list]
collect_list(col)
是Hive中常用的聚合函数,用于将分组内的某列值(col
)收集到一个数组中。它的核心作用是将多行数据合并为单行的数组结构,常用于数据重组或复杂分析场景。以下是详细说明和示例:
一、函数特点
- 分组聚合:需配合
GROUP BY
使用,将每个分组内的col
值收集为数组。 - 保留重复值:与
collect_set(col)
不同,collect_list
不会去重,保留所有原始值(包括重复值)。 - 顺序不确定:默认不保证数组内元素的顺序(除非配合窗口函数
ORDER BY
)。
二、典型应用场景
- 用户行为序列分析:将用户的多次操作按时间串联为行为路径。
- 数据结构转换:将行式存储的数据转为列式(如将多行商品标签转为单个商品的标签数组)。
- 复杂统计:计算每个分组内的所有值的列表(如收集每个班级的所有学生成绩)。
三、示例演示
场景1:用户订单列表收集
需求:收集每个用户的所有订单ID,生成用户ID → [订单ID列表]
的映射。
数据:
user_id | order_id------------------1 | 10011 | 10022 | 10032 | 1003 -- 重复订单3 | 1004
HQL:
SELECT user_id, collect_list(order_id) AS order_list -- 收集订单ID到数组FROM ordersGROUP BY user_id;
结果:
user_id | order_list---------------------1 | [1001, 1002]2 | [1003, 1003] -- 保留重复值3 | [1004]
场景2:按时间排序的用户行为路径
需求:将用户的点击行为按时间顺序串联为路径(如首页→商品页→购物车
)。
数据(user_behavior
表):
user_id | action_time | page-----------------------------------1 | 2025-07-24 10:00:00 | 首页1 | 2025-07-24 10:05:00 | 商品页1 | 2025-07-24 10:10:00 | 购物车2 | 2025-07-24 09:30:00 | 搜索页2 | 2025-07-24 09:40:00 | 商品页
HQL:
SELECT user_id, concat_ws(\'→\', collect_list(page ORDER BY action_time)) AS behavior_pathFROM user_behaviorGROUP BY user_id;
结果:
user_id | behavior_path------------------------1 | 首页→商品页→购物车2 | 搜索页→商品页
关键点:
ORDER BY action_time
确保数组元素按时间排序。concat_ws(\'→\', ...)
将数组元素用→
连接为字符串。
场景3:JSON数组生成(结合explode
反向操作)
需求:将每个商品的多个标签从多行转为JSON数组格式。
数据(product_tags
表):
product_id | tag-----------------101 | 电子产品101 | 手机102 | 服装102 | 男装102 | 休闲装
HQL:
SELECT product_id, collect_list(tag) AS tags_array -- 生成标签数组FROM product_tagsGROUP BY product_id;
结果:
product_id | tags_array-------------------------101 | [\"电子产品\", \"手机\"]102 | [\"服装\", \"男装\", \"休闲装\"]
延伸:若需转为JSON字符串,可结合to_json()
函数:
to_json(collect_list(tag)) AS tags_json -- 输出:\"[\"电子产品\",\"手机\"]\"
四、注意事项
- 内存风险:若单个分组的数据量过大(如某个用户有百万级订单),可能导致OOM(内存溢出),需控制分组数据规模或增加内存。
- 与
collect_set
对比:collect_list
保留重复值,且不保证顺序(除非显式ORDER BY
)。collect_set
自动去重,但同样不保证顺序。
- 数组长度限制:默认无限制,但过长的数组会影响性能,建议结合业务逻辑提前过滤无效数据。
五、性能优化建议
- 过滤先行:在
GROUP BY
前通过WHERE
减少数据量,避免不必要的计算。
示例:SELECT user_id, collect_list(order_id)FROM ordersWHERE order_date >= \'2025-01-01\' -- 先过滤近一年订单GROUP BY user_id;
- 配合窗口函数排序:若需严格按时间排序,可先通过窗口函数生成排序字段,再
collect_list
。WITH sorted_orders AS ( SELECT user_id, order_id, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY order_time) AS rn FROM orders)SELECT user_id, collect_list(order_id ORDER BY rn) AS ordered_ordersFROM sorted_ordersGROUP BY user_id;
通过collect_list
,可高效地将多行数据合并为结构化数组,为复杂分析(如路径挖掘、序列预测)提供基础,是Hive中处理“一对多”关系的核心工具之一。