Mysql中GROUP_CONCAT分组聚合函数的使用以及示例

一、函数定义与基础语法

GROUP_CONCAT(
    [DISTINCT] 字段名
    [ORDER BY 排序字段 [ASC|DESC]]
    [SEPARATOR '分隔符']
)

默认行为:连接非NULL值,默认逗号分隔

长度限制:受group_concat_max_len控制(默认1024字节)

二、核心使用场景与示例

1. 基础字符串连接

-- 连接部门所有员工姓名
SELECT
    dept_id,
    GROUP_CONCAT(employee_name) AS members
FROM employees
GROUP BY dept_id;

输出示例:

| dept_id | members          |
|---------|------------------|
| 1       | 张三,李四,王五    |

2. 去重连接(DISTINCT)

-- 连接不重复的城市名
SELECT
    country,
    GROUP_CONCAT(DISTINCT city) AS cities
FROM locations
GROUP BY country;

3. 自定义排序(ORDER BY)

-- 按入职时间倒序连接
SELECT
    dept_id,
    GROUP_CONCAT(
        employee_name
        ORDER BY hire_date DESC
        SEPARATOR ' | '
    ) AS seniority_list
FROM employees
GROUP BY dept_id;

4. 多字段组合

-- 连接姓名+工号
SELECT
    project_id,
    GROUP_CONCAT(
        CONCAT(name,'(',emp_id,')')
        SEPARATOR '; '
    ) AS project_team
FROM project_members
GROUP BY project_id;

三、高级应用技巧

1. 处理NULL值

-- 跳过NULL值(默认行为)
GROUP_CONCAT(IFNULL(field, 'N/A'))
 
-- 包含NULL占位
GROUP_CONCAT(field SEPARATOR '|')

2. 动态设置长度

-- 会话级调整(最大1MB)
SET SESSION group_concat_max_len = 1024 * 1024;

3. 嵌套JSON输出(MySQL 8.0+)

SELECT
    dept_id,
    JSON_ARRAYAGG(
        JSON_OBJECT('name', name, 'id', emp_id)
    ) AS member_json
FROM employees
GROUP BY dept_id;

4. 与CONCAT_WS配合

-- 智能处理空值
SELECT
    GROUP_CONCAT(
        CONCAT_WS(':',
            NULLIF(first_name,''),
            NULLIF(last_name,'')
        )
        SEPARATOR '\n'
    ) AS full_names
FROM users;

五、业务使用示例

  <select id= "pageAlarmEvent" resultMap= "PageResultMap">
    select
    ae.id,
    ae.event_name,
    ae.rule_name,
    ae.monitoring,
    ae.warehouse_id,
    ae.level,
    ar.time_interval,
    GROUP_CONCAT(an.title ORDER BY aen.id SEPARATOR ', ') AS notificationIdList,
    ae.notification_time,
    ae.start_time,
    ae.end_time,
    ae.is_next,
    ae.event_status,
    ae.update_user_id,
    ae.update_time
    FROM
    alarm_event ae
    LEFT JOIN
    alarm_rule ar ON ae.rule_id = ar.id
    LEFT JOIN
    alarm_event_notification aen ON ae.id = aen.event_id and aen.is_delete = 0
    LEFT JOIN
    alarm_notification an ON aen.notification_id = an.id
    <where>
      ae.is_delete = 0
      AND ae.company_id=#{companyId}
      <!-- 添加筛选条件 -->
      <if test="queryParam.warehouseId != null and queryParam.warehouseId != ''">
        AND ae.warehouse_id  = #{queryParam.warehouseId}
      </if>
      <if test="queryParam.tankId != null">
        AND ae.tank_id  = #{queryParam.tankId}
      </if>
      <if test="queryParam.level != null">
        AND ae.level  = #{queryParam.level}
      </if>
      <if test="queryParam.eventName != null and queryParam.eventName != ''">
        AND ae.event_name  LIKE CONCAT('%', #{queryParam.eventName}, '%')
      </if>
      <if test="queryParam.eventStatus != null">
        AND ae.event_status  = #{queryParam.eventStatus}
      </if>
    </where>
    GROUP BY
    ae.id,
    ae.event_name,
    ae.rule_name,
    ae.monitoring,
    ae.level,
    ae.warehouse_id,
    ar.time_interval,
    ae.notification_time,
    ae.start_time,
    ae.end_time,
    ae.is_next,
    ae.event_status,
    ae.update_user_id,
    ae.update_time
    <!-- 添加排序条件 -->
    ORDER BY ae.update_time  DESC
  </select>


场景描述

某告警事件ID= "event_123"关联了3条通知:

aen.id an.title

88 温度过高

92 压力异常

95 阀门泄漏

执行过程

按aen.id 排序得到序列:88 → 92 → 95

提取对应an.title :温度过高 → 压力异常 → 阀门泄漏

用分隔符连接:"温度过高, 压力异常, 阀门泄漏"

最终结果

{
  "id": "event_123",
  "notificationIdList": "温度过高, 压力异常, 阀门泄漏"
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

霸道流氓气质

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值