GROUP_CONCAT 函数用法总结

在 Doris 中,GROUP_CONCAT 是常用的聚合函数,用于将分组内某列的多个值拼接成一个字符串。它支持通过 ORDER BY 对拼接的元素排序,通过 SEPARATOR 指定元素间的分隔符(默认分隔符为英文逗号 ,)。以下从基础语法、核心用法(含排序 + 自定义分隔符)、注意事项、常见场景四个维度进行总结,确保覆盖实际开发中的高频需求。

一、基础语法

Doris 中 GROUP_CONCAT 的完整语法格式如下(兼容 MySQL 语法,降低学习成本):

sql

GROUP_CONCAT(
    [DISTINCT]  -- 可选,去重后再拼接
    列名/表达式  -- 必选,需拼接的列或计算表达式(如 IF、CASE 结果)
    [ORDER BY 排序列 [ASC/DESC]]  -- 可选,对拼接的元素排序
    [SEPARATOR '分隔符']  -- 可选,指定元素间的分隔符(默认是 ',')
)
关键参数说明

参数作用是否必选
列名/表达式指定分组内需要拼接的数据来源(如某列值、或 IF(status=1, '正常', '异常') 这类计算结果)
DISTINCT可选,对拼接的元素去重(例如同一分组内有重复值,只保留一个)
ORDER BY 排序列可选,对分组内待拼接的元素按指定列排序(确保拼接结果的顺序可预期)
SEPARATOR '分隔符'可选,指定元素间的分隔符(如 `'''-'、空字符串 ''等),默认是','`

二、核心用法总结(含示例)

以下示例基于一张模拟的 user_orders 表(数据如下),覆盖 GROUP_CONCAT 与 ORDER BYSEPARATOR 的组合用法:

user_idorder_idorder_dateproduct_nameamount
10150012024-05-01手机3999
10150032024-05-03耳机299
10150022024-05-02充电器89
10250042024-05-01键盘199
10250052024-05-02鼠标99
1. 基础用法:默认分隔符(无排序)

不指定 ORDER BY 和 SEPARATOR,默认按数据存储顺序拼接,分隔符为 ,
需求:按 user_id 分组,拼接每个用户的订单 ID。

sql

SELECT
  user_id,
  GROUP_CONCAT(order_id) AS order_id_list  -- 默认用 ',' 拼接,无排序
FROM user_orders
GROUP BY user_id;

结果(注意:101 的订单 ID 顺序未排序,与存储顺序一致):

user_idorder_id_list
1015001,5003,5002
1025004,5005
2. 结合 ORDER BY:按指定字段排序后拼接

实际场景中,常需要按时间、数值等排序后拼接(如按订单日期升序),确保结果顺序可预期。
需求:按 user_id 分组,按 order_date 升序拼接每个用户的 “订单 ID - 商品名”。

sql

SELECT
  user_id,
  -- 拼接格式:order_id-product_name,按 order_date 升序排序
  GROUP_CONCAT(
    CONCAT(order_id, '-', product_name)  -- 自定义拼接元素格式
    ORDER BY order_date ASC  -- 按订单日期升序
  ) AS order_product_list
FROM user_orders
GROUP BY user_id;

结果(101 的订单按日期从早到晚排序,5001→5002→5003):

user_idorder_product_list
1015001 - 手机,5002 - 充电器,5003 - 耳机
1025004 - 键盘,5005 - 鼠标
3. 结合 SEPARATOR:自定义分隔符

默认分隔符是 ,,可通过 SEPARATOR 指定其他分隔符(如 |-、空字符串等)。
需求:按 user_id 分组,用 | 分隔符拼接商品名,且按金额降序排序。

sql

SELECT
  user_id,
  GROUP_CONCAT(
    product_name
    ORDER BY amount DESC  -- 按订单金额降序(手机>耳机>充电器)
    SEPARATOR '|'         -- 自定义分隔符为 '|'
  ) AS product_list_by_amount
FROM user_orders
GROUP BY user_id;

结果(101 的商品按金额从高到低排序,分隔符为 |):

user_idproduct_list_by_amount
101手机耳机充电器
102键盘鼠标
4. 含 DISTINCT:去重后拼接

若分组内某列有重复值(如同一用户多次购买同一商品),可通过 DISTINCT 去重后再拼接。
需求:按 user_id 分组,去重后拼接用户购买的商品类别(假设新增 category 列,存在重复)。

sql

-- 模拟表新增 category 列后的数据(101重复购买“数码”类商品)
SELECT
  user_id,
  GROUP_CONCAT(
    DISTINCT category  -- 去重:同一类别只保留一次
    ORDER BY category ASC
    SEPARATOR '-'
  ) AS distinct_category
FROM user_orders
GROUP BY user_id;

结果(101 的 “数码” 类别去重后只出现一次):

user_iddistinct_category
101数码 - 配件
102外设
5. 空字符串分隔符(无缝拼接)

若需要拼接后无分隔符(如将数值拼接成一串数字),可指定 SEPARATOR ''(空字符串)。
需求:按 user_id 分组,将订单金额按日期升序无缝拼接(如 399929989)。

sql

SELECT
  user_id,
  GROUP_CONCAT(
    amount
    ORDER BY order_date ASC
    SEPARATOR ''  -- 空分隔符,无缝拼接
  ) AS amount_concat
FROM user_orders
GROUP BY user_id;

结果(101 的金额按日期拼接为 3999(5.1)+89(5.2)+299(5.3)= 399989299):

user_idamount_concat
101399989299
10219999

三、注意事项(避坑指南)

  1. 必须搭配 GROUP BY
    GROUP_CONCAT 是聚合函数,不能单独使用,必须配合 GROUP BY 指定分组字段(除非仅聚合全表数据,此时 GROUP BY 可省略,但不推荐,可读性差)。
    ❌ 错误示例(无 GROUP BY,全表聚合,仅返回 1 行):

    sql

    SELECT GROUP_CONCAT(product_name);  -- 不推荐,需明确分组逻辑
    
     

    ✅ 正确示例(按 user_id 分组):

    sql

    SELECT user_id, GROUP_CONCAT(product_name) FROM user_orders GROUP BY user_id;
    
  2. 排序字段需在分组上下文内
    ORDER BY 后指定的 “排序列”,必须是 分组字段、聚合列、或原始表中存在的列(不能是其他未关联的列)。
    ❌ 错误示例(排序列 other_col 不在表中):

    sql

    SELECT user_id, GROUP_CONCAT(product_name ORDER BY other_col) FROM user_orders GROUP BY user_id;
    
  3. 结果长度限制(默认 1024 字符)
    Doris 中 GROUP_CONCAT 的默认结果长度限制为 1024 个字符,若拼接后字符串超长,会被截断(导致数据丢失)。

    • 查看当前限制:执行 SHOW VARIABLES LIKE 'group_concat_max_len';
    • 临时调整限制(会话级):执行 SET group_concat_max_len = 102400;(设置为 100KB,根据需求调整)
    • 永久调整:需在 Doris 配置文件中修改 group_concat_max_len 参数(需重启服务)。
  4. NULL 值处理
    若待拼接的列包含 NULLGROUP_CONCAT 会自动忽略 NULL 值(不拼接 NULL,也不会用分隔符填充)。
    示例:若某用户的 product_name 有 NULL,拼接结果会跳过该值:

    sql

    -- 假设 user_id=101 有一条 product_name=NULL 的数据
    SELECT user_id, GROUP_CONCAT(product_name) FROM user_orders GROUP BY user_id;
    -- 结果:101 → 手机,耳机,充电器(NULL被忽略)
    
  5. 与 CASE/IF 结合的表达式拼接
    支持拼接 “条件表达式” 的结果(如将状态值转为文字后拼接),语法上直接将表达式作为 GROUP_CONCAT 的参数即可。
    示例:拼接订单状态(1 = 已支付,0 = 未支付):

    sql

    SELECT
      user_id,
      GROUP_CONCAT(
        IF(status=1, '已支付', '未支付')  -- 条件表达式
        ORDER BY order_date
        SEPARATOR '|'
      ) AS order_status_list
    FROM user_orders
    GROUP BY user_id;
    

四、常见业务场景

场景实现 SQL 示例
拼接用户的所有订单号SELECT user_id, GROUP_CONCAT(order_id SEPARATOR ',') FROM orders GROUP BY user_id;
按时间排序拼接操作日志SELECT user_id, GROUP_CONCAT(log_content ORDER BY log_time SEPARATOR ';') FROM logs GROUP BY user_id;
去重拼接用户标签`SELECT user_id, GROUP_CONCAT(DISTINCT tag SEPARATOR '') FROM user_tags GROUP BY user_id;`
无缝拼接数值成编码SELECT dept_id, GROUP_CONCAT(emp_id ORDER BY emp_id SEPARATOR '') FROM employees GROUP BY dept_id;

总结

Doris 中的 GROUP_CONCAT 核心能力是 “分组拼接”,通过 ORDER BY 确保拼接顺序可控,通过 SEPARATOR 自定义分隔符,配合 DISTINCT 可实现去重拼接。实际使用时需注意 分组逻辑、结果长度限制、NULL 值处理,避免因语法或配置问题导致数据异常。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值