数组函数能做什么
数组类型配合函数族,可以在查询里完成分组内列表聚合、元素展开与检索: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 等更省内存的方式。