MySQL中GROUP_CONCAT函数详解 | 按日期分组拼接销售产品经典案例

前言

在日常的SQL业务开发中,我们经常遇到分组统计+分组内字段拼接 的需求,比如按日期统计每日销售的产品数量、并将当日销售的所有产品名称拼接成一个字符串展示。这类需求用普通的GROUP BY分组+聚合函数是无法实现的,而MySQL的GROUP_CONCAT()函数就是专门解决这类场景的「神器」,今天结合经典的「按日期分组统计销售产品」SQL案例,彻底吃透GROUP_CONCAT()的用法和核心细节。

一、先看完整业务场景SQL(经典面试/业务题)

需求说明

现有销售记录表Activities,表中核心字段为sell_date(销售日期)、product(销售产品名),要求:

  1. 按销售日期进行分组
  2. 统计每日不同产品的销售数量
  3. 展示每日销售的所有不同产品名称,产品名称按字母升序排列、用英文逗号分隔
  4. 最终结果按销售日期升序排序

实现SQL

sql 复制代码
select
    sell_date,
    count(distinct product) as num_sold, -- 统计每日售卖的不同产品数
    group_concat(distinct product order by product separator ',') as products -- 拼接每日售卖的产品名
from
    Activities
group by
    sell_date -- 核心:按日期分组
order by
    sell_date ASC;

二、GROUP_CONCAT() 函数核心介绍

✅ 函数定义

GROUP_CONCAT() 是MySQL专属的分组聚合函数 ,作用是:将分组后的同一组内的指定字段的所有值,拼接成一个完整的字符串返回

✅ 函数核心语法格式

sql 复制代码
GROUP_CONCAT([DISTINCT] 字段名 [ORDER BY 字段排序规则] [SEPARATOR '分隔符'])

✅ 语法各部分解析(重中之重,全部常用)

1. 必选核心:GROUP_CONCAT(字段名)

最基础用法,无任何修饰,直接拼接分组内指定字段的所有值。

  • 特点:会保留字段的重复值
  • 拼接分隔符:默认使用 英文逗号, 分隔
  • 排序:默认按字段值的自然顺序排序,无指定规则
2. 核心修饰1:DISTINCT 去重关键字
sql 复制代码
GROUP_CONCAT(DISTINCT 字段名)

这是业务中极高频的用法 ,作用是:对分组内要拼接的字段值先去重,再拼接

比如本文案例中,同一天可能同一个产品卖出多次,我们只需要展示「当日卖了哪些产品」,而非「每次卖出的产品」,所以必须加DISTINCT product,避免产品名重复拼接。

3. 核心修饰2:ORDER BY 排序子句
sql 复制代码
GROUP_CONCAT(字段名 ORDER BY 字段名 [ASC/DESC])

作用是:对分组内要拼接的字段值,按照指定规则排序后再拼接

比如本文案例中要求产品名按字母升序排列,所以写order by product(默认ASC升序,可省略),如果需要降序则写order by product DESC

4. 核心修饰3:SEPARATOR '分隔符' 分隔符指定
sql 复制代码
GROUP_CONCAT(字段名 SEPARATOR '自定义分隔符')

作用是:指定拼接后的分隔符,替换默认的英文逗号

  • 支持任意自定义分隔符:逗号,、竖线|、横线-、空格 、分号;

比如本文案例指定用英文逗号分隔,所以写separator ',',这也是最常用的分隔符。

✅ 完整组合用法(案例同款,开发中最常用)

sql 复制代码
GROUP_CONCAT(DISTINCT 字段名 ORDER BY 字段名 SEPARATOR '分隔符')

先去重 → 再排序 → 最后按指定分隔符拼接,完美解决绝大多数分组拼接需求。

三、GROUP_CONCAT() 核心注意事项(避坑必备)

✅ 注意1:必须配合 GROUP BY 使用,否则无意义

GROUP_CONCAT()分组聚合函数 ,和COUNT()SUM()MAX()等函数的特性一致:

  • 如果有GROUP BY,则按分组维度拼接每组的字段值
  • 如果没有GROUP BY,则整张表视为「一个分组」,会把指定字段的所有值拼接成一个字符串

切记:该函数不能脱离分组场景单独使用,否则业务逻辑一定错误。

✅ 注意2:默认有长度限制,超出会被截断

这是最容易踩坑的点 ,MySQL对GROUP_CONCAT()的返回结果,默认有最大长度限制 1024 字节

  • 如果分组内要拼接的内容过多(比如一个分组有上百个产品名),拼接后的字符串长度超过1024字节,超出部分会被直接截断,导致返回结果不完整。
✅ 解决方案:修改长度限制(两种方式)
方式1:临时修改(当前会话有效,重启MySQL失效)
sql 复制代码
-- 设置全局的拼接长度限制,建议设置为合适的值,比如102400(100KB)
SET GLOBAL group_concat_max_len = 102400;
-- 设置当前会话的拼接长度限制
SET SESSION group_concat_max_len = 102400;
方式2:永久修改(修改配置文件,推荐生产环境使用)

编辑MySQL的配置文件my.cnf(Linux)或my.ini(Windows),在[mysqld]节点下添加配置:

ini 复制代码
[mysqld]
group_concat_max_len = 102400

添加后重启MySQL服务,配置永久生效。

✅ 注意3:与 CONCAT() 的区别,千万不要混淆

很多初学者会把GROUP_CONCAT()CONCAT()搞混,这两个函数完全不同,用途天差地别,这里做清晰区分,杜绝混淆:

  1. CONCAT(字段1,字段2,...)行级拼接 ,作用于「单行数据」,将同一行的多个字段值拼接成一个字符串,不分组、聚合相关
    • 例:CONCAT(name, '-', price) → 把单行的姓名和价格拼接成「张三-99」
  2. GROUP_CONCAT(字段)分组拼接 ,作用于「分组后的多行数据」,将同一分组的多行的同一个字段 值拼接成一个字符串,必须分组、属于聚合函数
    • 例:本文案例中,把「2026-01-20」这个分组的所有产品名拼接成「苹果,香蕉,橙子」

✅ 一句话总结区别:CONCAT是同行多字段拼接,GROUP_CONCAT是同组同字段多行拼接

四、拓展:常见衍生用法

✅ 用法1:拼接多个字段+自定义分隔符

如果需要在分组内,拼接「产品名+价格」这类多个字段的组合值,可以嵌套CONCAT()使用:

sql 复制代码
select
    sell_date,
    group_concat(DISTINCT CONCAT(product, '-', price) ORDER BY product separator ';') as product_price
from Activities
group by sell_date;

效果:拼接出「苹果-5.9;香蕉-3.9;橙子-4.5」这样的组合字符串。

✅ 用法2:结合其他聚合函数使用

COUNT(DISTINCT)SUM()等聚合函数完美兼容,也是本文案例的写法,这是业务开发中的标配:

sql 复制代码
select
    sell_date,
    count(distinct product) as 销售产品数,
    sum(amount) as 当日销售额,
    group_concat(distinct product order by product) as 销售产品列表
from Activities
group by sell_date;

五、总结

✅ 核心知识点

  1. GROUP_CONCAT()是MySQL分组聚合函数,作用是分组拼接同组字段值为字符串
  2. 完整语法:GROUP_CONCAT([DISTINCT] 字段 [ORDER BY 字段] [SEPARATOR '分隔符'])
  3. 三大核心修饰:DISTINCT去重、ORDER BY排序、SEPARATOR指定分隔符,可组合使用;
  4. 必须配合GROUP BY使用,否则无分组意义;
  5. 默认长度限制1024字节,超长需手动修改配置;
  6. CONCAT()的核心区别:分组多行单字段拼接 vs 单行多字段拼接。

✅ 业务适用场景

除了本文的「按日期分组拼接销售产品」,该函数还适用于所有需要分组聚合+内容拼接的场景:

  • 按用户分组,拼接用户所有的下单商品;
  • 按班级分组,拼接班级所有的学生姓名;
  • 按部门分组,拼接部门所有的员工工号;
  • 按订单分组,拼接订单所有的商品规格。

GROUP_CONCAT()是MySQL开发中非常实用的函数,掌握其用法和避坑点,能极大提升我们处理分组拼接类需求的效率,希望本文的讲解能帮助大家彻底吃透这个函数!


博主留言

如果本文对你有帮助,欢迎点赞+收藏+关注!后续会持续更新MySQL高频函数和经典业务SQL案例,一起夯实数据库基础,高效开发~

相关推荐
松涛和鸣12 小时前
72、IMX6ULL驱动实战:设备树(DTS/DTB)+ GPIO子系统+Platform总线
linux·服务器·arm开发·数据库·单片机
likangbinlxa12 小时前
【Oracle11g SQL详解】UPDATE 和 DELETE 操作的正确使用
数据库·sql
r i c k13 小时前
数据库系统学习笔记
数据库·笔记·学习
野犬寒鸦13 小时前
从零起步学习JVM || 第一章:类加载器与双亲委派机制模型详解
java·jvm·数据库·后端·学习
IvorySQL14 小时前
PostgreSQL 分区表的 ALTER TABLE 语句执行机制解析
数据库·postgresql·开源
·云扬·14 小时前
MySQL 8.0 Redo Log 归档与禁用实战指南
android·数据库·mysql
IT邦德14 小时前
Oracle 26ai DataGuard 搭建(RAC到单机)
数据库·oracle
惊讶的猫14 小时前
redis分片集群
数据库·redis·缓存·分片集群·海量数据存储·高并发写
不爱缺氧i15 小时前
完全卸载MariaDB
数据库·mariadb
纤纡.15 小时前
Linux中SQL 从基础到进阶:五大分类详解与表结构操作(ALTER/DROP)全攻略
linux·数据库·sql