前言
在日常的SQL业务开发中,我们经常遇到分组统计+分组内字段拼接 的需求,比如按日期统计每日销售的产品数量、并将当日销售的所有产品名称拼接成一个字符串展示。这类需求用普通的GROUP BY分组+聚合函数是无法实现的,而MySQL的GROUP_CONCAT()函数就是专门解决这类场景的「神器」,今天结合经典的「按日期分组统计销售产品」SQL案例,彻底吃透GROUP_CONCAT()的用法和核心细节。
一、先看完整业务场景SQL(经典面试/业务题)
需求说明
现有销售记录表Activities,表中核心字段为sell_date(销售日期)、product(销售产品名),要求:
- 按销售日期进行分组
- 统计每日不同产品的销售数量
- 展示每日销售的所有不同产品名称,产品名称按字母升序排列、用英文逗号分隔
- 最终结果按销售日期升序排序
实现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()搞混,这两个函数完全不同,用途天差地别,这里做清晰区分,杜绝混淆:
- CONCAT(字段1,字段2,...) :行级拼接 ,作用于「单行数据」,将同一行的多个字段值拼接成一个字符串,不分组、聚合相关 。
- 例:
CONCAT(name, '-', price)→ 把单行的姓名和价格拼接成「张三-99」
- 例:
- 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;
五、总结
✅ 核心知识点
GROUP_CONCAT()是MySQL分组聚合函数,作用是分组拼接同组字段值为字符串;- 完整语法:
GROUP_CONCAT([DISTINCT] 字段 [ORDER BY 字段] [SEPARATOR '分隔符']); - 三大核心修饰:
DISTINCT去重、ORDER BY排序、SEPARATOR指定分隔符,可组合使用; - 必须配合
GROUP BY使用,否则无分组意义; - 默认长度限制1024字节,超长需手动修改配置;
- 和
CONCAT()的核心区别:分组多行单字段拼接 vs 单行多字段拼接。
✅ 业务适用场景
除了本文的「按日期分组拼接销售产品」,该函数还适用于所有需要分组聚合+内容拼接的场景:
- 按用户分组,拼接用户所有的下单商品;
- 按班级分组,拼接班级所有的学生姓名;
- 按部门分组,拼接部门所有的员工工号;
- 按订单分组,拼接订单所有的商品规格。
GROUP_CONCAT()是MySQL开发中非常实用的函数,掌握其用法和避坑点,能极大提升我们处理分组拼接类需求的效率,希望本文的讲解能帮助大家彻底吃透这个函数!
博主留言
如果本文对你有帮助,欢迎点赞+收藏+关注!后续会持续更新MySQL高频函数和经典业务SQL案例,一起夯实数据库基础,高效开发~