首页/数据/NoSQL 速查/数组函数与 groupArray
ClickHouse56 条

数组函数与 groupArray

数组类型配合函数族可以完成分组内列表聚合、元素展开与检索:groupArray 收集、arrayJoin 展开、arrayDistinct 去重、has/indexOf 判断元素。

NoSQL 速查数据更新于 2026-10-13

数组函数能做什么

数组类型配合函数族,可以在查询里完成分组内列表聚合、元素展开与检索:groupArray 把组内值收成一个数组,arrayJoin 把数组展开成多行,arrayDistinct、arraySort、arraySlice、has、indexOf、length 负责去重、排序、切片与查找。它们让"每个用户的全部行为"这类问题可以用一条语句表达。

展开会改变行数

arrayJoin 是最需要小心的一类函数:它把一行展开成多行,因此展开后再聚合等于对展开后的数据重新统计,与原始行数的口径不同。做漏斗或去重统计时,先想清楚当前口径是事件数还是用户数,再决定在哪一层做展开。

基本信息

聚合侧groupArray、groupUniqArray、groupArrayInsertAt、topK
数组侧arrayJoin、arraySort、arrayDistinct、arraySlice、has、indexOf、length
组合用法arrayJoin(groupArray(x)) 在分组与展开之间来回转换
内存特性分组内数组常驻内存,受 max_memory_usage 限制
适用版本ClickHouse 各主流版本均支持

示例

示例
SELECT user_id, groupArray(event_type) AS events, length(events) AS cnt
FROM events
GROUP BY user_id
ORDER BY cnt DESC
LIMIT 5;

-- 展开:一行变多行
SELECT arrayJoin([1, 2, 3]) AS x;

-- 合并两个数组并去重
SELECT arrayDistinct(arrayConcat([1, 2], [2, 3]));

-- 判断某元素是否在组内出现过
SELECT has(groupArray(event_type), 'click') AS has_click
FROM events GROUP BY user_id LIMIT 5;

典型使用场景

  • 行为序列:把同一用户的事件按时间收成数组再分析
  • 展开统计:把数组字段展开成行做逐元素计数
  • 去重列表:用 groupUniqArray 直接拿到去重后的取值集合
  • 集合判断:用 has、indexOf 判断某行为是否出现及出现的顺序
  • 体积控制:用 arraySlice 截断长数组,减少返回数据量

常用函数对照

函数作用注意
groupArray组内值收成数组分组太大时内存占用高
groupUniqArray组内去重后收成数组结果不保证稳定顺序
arrayJoin数组展开为多行会改变后续聚合的行数口径
arraySlice截取数组片段常用于只取最近若干条
has / indexOf判断元素存在与位置按元素逐项比较
arrayJoin 会把一行展开成多行,展开后再聚合相当于全局重算,注意与原始行数口径区分,漏斗类分析尤其容易在这里算错。
对超大分组使用 groupArray 会占用大量内存,触发内存上限时报错;先缩小分组范围,或改用 groupUniqArray 等更省内存的方式。

易错点

  • 对超大分组使用 groupArray 会占用大量内存,触发内存限制报错时先缩小分组范围
  • arrayJoin 与 GROUP BY 同用时的语义容易混淆,先在小数据集上验证行数再上生产
  • 把数组函数当全局集合运算会算错口径,它们只作用在分组或单行内部
  • groupArray 的结果顺序不保证稳定,需要顺序时用 arraySort 或 groupArrayInsertAt 显式控制

数据来源与参考

  • ClickHouse Docs: Array functions
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌