doris 中 array_agg函数用法总结

在 Apache Doris 中,array_agg()聚合函数 ,用于将指定列的多行数据(通常配合 GROUP BY 使用)合并为一个数组(Array),是处理 "多行转单个数组" 场景的核心函数。以下从基础用法、语法规则、常见场景、注意事项等维度进行全面总结。

一、核心定义与语法

1. 功能定位

GROUP BY 分组后的某一列(或表达式结果)的所有非 NULL 值,按数据原始顺序(Doris 2.0+ 支持指定排序,旧版本依赖存储顺序)聚合为一个数组。

  • 若分组内无数据或全为 NULL,返回空数组 [] (而非 NULL)。
  • 仅支持 Aggregate 聚合模型、Unique 模型、Duplicate 模型(所有 Doris 主流表模型)。
2. 语法格式

sql

复制代码
array_agg(expr [ORDER BY sort_expr [ASC|DESC]] [SEPARATOR 'delimiter'])
参数 说明
expr 必选,需聚合的列或表达式(支持数值、字符串、日期等 Doris 支持的基础类型)。
ORDER BY 可选,指定数组内元素的排序规则(Doris 2.0+ 新增,旧版本无此功能)。
SEPARATOR 可选,仅当 expr 为字符串类型时生效,指定数组转字符串时的分隔符(默认无)。

二、基础用法示例

假设存在表 student_score,存储学生的科目成绩,结构与数据如下:

student_id subject score
101 Math 90
101 English 85
101 Chinese 95
102 Math 78
102 English 88
103 Math NULL
1. 基础聚合:分组合并为数组

student_id 分组,将每个学生的科目、成绩分别聚合为数组:

sql

复制代码
SELECT
  student_id,
  array_agg(subject) AS subject_list,  -- 字符串数组
  array_agg(score) AS score_list       -- 数值数组(自动过滤 NULL)
FROM student_score
GROUP BY student_id;

结果

student_id subject_list score_list
101 ["Math","English","Chinese"] [90,85,95]
102 ["Math","English"] [78,88]
103 [] [] -- 无 subject 数据,返回空数组;score 为 NULL,也返回空数组
2. 带排序的聚合(Doris 2.0+)

student_id 分组,将成绩按降序聚合为数组(便于查看高分科目):

sql

复制代码
SELECT
  student_id,
  array_agg(subject ORDER BY score DESC) AS subject_sorted_by_score,
  array_agg(score ORDER BY score DESC) AS score_sorted
FROM student_score
GROUP BY student_id;

结果(101 学生的成绩降序排列):

student_id subject_sorted_by_score score_sorted
101 ["Chinese","Math","English"] [95,90,85]
3. 字符串数组指定分隔符(SEPARATOR)

若需将字符串数组转为用特定符号分隔的字符串(如用 , 连接科目),可搭配 SEPARATOR

sql

复制代码
SELECT
  student_id,
  array_agg(subject SEPARATOR ',') AS subject_str  -- 数组转字符串,用逗号分隔
FROM student_score
GROUP BY student_id;

结果

student_id subject_str
101 Math,English,Chinese
102 Math,English

三、进阶场景与组合用法

array_agg() 常与数组函数 (如 array_length()array_contains())或窗口函数结合,实现更复杂的分析需求。

1. 统计数组长度(配合 array_length()

计算每个学生的考试科目数量(即数组的元素个数):

sql

复制代码
SELECT
  student_id,
  array_agg(subject) AS subject_list,
  array_length(array_agg(subject)) AS subject_count  -- 统计数组长度
FROM student_score
GROUP BY student_id;

结果

student_id subject_list subject_count
101 ["Math","English","Chinese"] 3
102 ["Math","English"] 2
2. 过滤数组元素(配合 array_filter()

聚合成绩后,过滤出分数 ≥ 90 的成绩(先聚合再过滤):

sql

复制代码
SELECT
  student_id,
  array_filter(
    array_agg(score),  -- 待过滤的数组
    x -> x >= 90       -- 过滤条件:元素 ≥ 90
  ) AS high_score_list
FROM student_score
GROUP BY student_id;

结果

student_id high_score_list
101 [90,95]
102 [] -- 无符合条件的成绩
103 []
3. 窗口函数场景(不分组,保留原始行)

若需保留每一行数据,同时显示 "该学生的所有成绩"(不压缩行),可结合 OVER(PARTITION BY) 窗口:

sql

复制代码
SELECT
  student_id,
  subject,
  score,
  array_agg(score) OVER (PARTITION BY student_id) AS all_scores_of_student
FROM student_score;

结果(101 学生的每一行都附带其所有成绩):

student_id subject score all_scores_of_student
101 Math 90 [90,85,95]
101 English 85 [90,85,95]
101 Chinese 95 [90,85,95]
102 Math 78 [78,88]

四、关键注意事项

  1. NULL 值处理
    array_agg()自动过滤 NULL ,即分组内若某行的 exprNULL,不会加入数组。例如 103 学生的 scoreNULL,聚合后 score_list 为空数组。

  2. 数据类型限制

    • 支持聚合基础类型 (int、string、date、double 等),不支持聚合 ArrayMapStruct 等复杂类型(即不能嵌套聚合 array_agg(array_col))。
    • 聚合后的数组元素类型与 expr 类型一致(如 exprint,数组为 Array<int>)。
  3. 排序功能的版本依赖
    ORDER BY 子句是 Doris 2.0 及以上版本新增的功能,旧版本(如 1.2、1.3)不支持,若需排序需先通过子查询排序,再聚合(但效果不稳定,建议升级版本)。

  4. 性能与数据量限制

    • 若分组内数据量极大(如超过 10 万行),聚合后的数组会占用较多内存,可能导致查询性能下降,建议通过业务逻辑拆分分组。
    • 数组元素个数无硬限制,但受 Doris 单条数据大小限制(默认单条数据不超过 100MB)。
  5. group_concat() 的区别

    • array_agg() 返回数组类型 ,可后续通过数组函数(如 array_contains())进一步处理;

    • group_concat() 返回字符串类型,仅用于直接展示,无法后续解析元素。

    • 示例对比: sql

      复制代码
      array_agg(subject) → ["Math","English"]  -- 数组
      group_concat(subject, ',') → "Math,English"  -- 字符串

五、常见问题排查

  1. 聚合后数组为空

    • 原因:分组内无数据,或所有 expr 均为 NULL
    • 排查:先执行 GROUP BY 查看分组行数,确认是否有有效数据。
  2. ORDER BY 不生效

    • 原因:使用的 Doris 版本低于 2.0,或 ORDER BY 后的字段未在 expr 中;
    • 解决:升级 Doris 版本,或确保 ORDER BY 字段与 expr 逻辑一致。
  3. 数组元素顺序异常

    • 原因:Doris 旧版本(<2.0)聚合顺序依赖数据存储顺序(非 SQL 执行顺序);
    • 解决:升级到 2.0+ 版本,通过 ORDER BY 显式指定顺序。

通过以上总结,可覆盖 array_agg() 在 Doris 中的绝大多数使用场景,结合实际业务需求(如多值聚合、数组过滤、窗口分析)灵活调用即可。

相关推荐
de_wizard3 小时前
DeepSeek API 调用 - Spring Boot 实现
windows·spring boot·后端
小学鸡!3 小时前
win10/win11下载安装Docker,Windows安装Docker Desktop 【保姆级教程】
windows·docker·容器
夜星辰20233 小时前
在 Ubuntu 里创建 Docker 容器,与在 Windows 上安装 VMware Workstation Pro 虚拟机的区别
windows·ubuntu·docker
姜太小白3 小时前
【其他】QEMU 在 Windows 和 CentOS 7 下安装及运行 ARM 操作系统指南
arm开发·windows·centos
私人珍藏库4 小时前
[Windows] 央视影音v6.0.4.1绿色版
windows·工具·软件·影音·多功能
金刚狼884 小时前
UUID和Name不在同一条BLE广播报文里
c++·windows
nudt_qxx4 小时前
Ubuntu 26.04 换国内源 清华源 阿里源 中科大源 华为源
linux·windows·ubuntu
桌面运维家5 小时前
Windows性能优化:任务管理器深度使用指南
windows·性能优化
攻城狮在此5 小时前
ping命令中TTL值是什么?详解与用法
linux·网络·windows