在日常数据库查询中,我们经常会遇到 “一对多” 关联场景 —— 比如一个店铺对应多个设备。当需要查询符合条件的店铺及关联设备时,直接关联查询会出现 “一个店铺对应多行设备” 的结果,不仅冗余,还不符合 “店铺不重复” 的展示需求。
本文就以 “店铺 - 设备” 关联查询为例,分享如何用GROUP_CONCAT函数实现 “一店一行,多设备名称逗号拼接” 的效果,解决数据重复问题。
我们有两张核心表,分别存储店铺信息和设备信息:
查询满足以下条件的数据:
最初的关联查询 SQL 如下:
SELECT
dept.id AS 店铺编号,
dept.name AS 店铺名称,
d.name AS 设备名称
FROM ai_ovopark_department dept
INNER JOIN ai_ovopark_device d
ON dept.id = d.deptId
WHERE
dept.brand_id = '30'
AND dept.openStatus = '1'
AND dept.inspection_status = 1
AND dept.indicator_status = 1
AND d.online = 0;
执行后会出现 “一个店铺对应多行” 的结果(如下表),不符合 “店铺不重复” 的需求:
店铺编号 | 店铺名称 | 设备名称 |
---|---|---|
101 | 北京店 | 摄像头 A |
101 | 北京店 | 传感器 B |
102 | 上海店 | 报警器 C |
要解决 “店铺不重复、设备名称合并” 的问题,核心是使用 MySQL 的GROUP_CONCAT函数 —— 它能将同一分组内的指定字段值拼接成一个字符串,再配合GROUP BY按店铺分组,即可实现 “一店一行”。
SELECT
dept.id AS 店铺编号,
dept.NAME AS 店铺名称,
dept.brand_id AS 品牌编号,
dept.openStatus AS 门店状态,
-- 合并设备名称,用逗号分隔
GROUP_CONCAT(d.NAME SEPARATOR ',') AS 设备名称列表
FROM
ai_ovopark_department dept
INNER JOIN ai_ovopark_device d ON dept.id = d.deptId
WHERE
-- 店铺条件
dept.brand_id = '30'
AND dept.openStatus = '1'
AND dept.inspection_status = 1
AND dept.indicator_status = 1
-- 设备条件
AND d.ONLINE = 0
-- 按店铺分组,确保每个店铺只出现一次
GROUP BY
dept.id,
dept.NAME,
dept.brand_id,
dept.openStatus;
执行后会得到 “一店一行,设备名称逗号拼接” 的清晰结果:
店铺编号 | 店铺名称 | 品牌编号 | 门店状态 | 巡检状态 | 商业状态 | 离线设备名称列表 |
---|---|---|---|---|---|---|
101 | 北京店 | 30 | 1 | 1 | 1 | 摄像头 A, 传感器 B |
102 | 上海店 | 30 | 1 | 1 | 1 | 报警器 C |
GROUP_CONCAT是 MySQL 中用于 “分组拼接” 的核心函数,理解它的用法能解决很多 “一对多” 数据合并场景。
GROUP_CONCAT( [DISTINCT] 字段名 -- DISTINCT:可选,去除重复值 [ORDER BY 字段名 ASC/DESC] -- 可选,对拼接的内容排序 [SEPARATOR '分隔符'] -- 可选,指定分隔符(默认是逗号))
GROUP_CONCAT(DISTINCT d.name ORDER BY d.name ASC SEPARATOR ',')
GROUP_CONCAT(d.name SEPARATOR '、') -- 结果:摄像头A、传感器B
-- 临时调整(当前会话生效)SET SESSION group_concat_max_len = 102400; -- 设为100KB-- 永久调整(需重启MySQL)SET GLOBAL group_concat_max_len = 102400;
根据实际需求,我们还可以对上述 SQL 进行灵活调整,适应不同场景:
如果需要显示 “符合条件的店铺,即使没有离线设备”(此时设备名称列表为空),可将INNER JOIN改为LEFT JOIN,并在WHERE中调整设备筛选条件(避免过滤掉无设备的店铺):
SELECT dept.id AS 店铺编号, dept.name AS 店铺名称, -- 无设备时显示空字符串(避免NULL) IFNULL(GROUP_CONCAT(d.name SEPARATOR ','), '') AS 离线设备名称列表FROM ai_ovopark_department dept-- 左关联:保留所有符合条件的店铺,即使无设备LEFT JOIN ai_ovopark_device d ON dept.id = d.deptId AND d.online = 0 -- 设备条件移到ON中,避免过滤店铺WHERE dept.brand_id = '30' AND dept.openStatus = '1' AND dept.inspection_status = 1 AND dept.indicator_status = 1GROUP BY dept.id, dept.name;
如果需要同时拼接设备名称和设备 ID(如 “摄像头 A (1001), 传感器 B (1002)”),可使用字符串拼接函数CONCAT配合GROUP_CONCAT:
GROUP_CONCAT( CONCAT(d.name, '(', d.deviceId, ')') -- 格式:设备名(设备ID) SEPARATOR ',') AS 离线设备信息列表
本文通过 “店铺 - 设备” 关联查询的实际场景,介绍了如何用GROUP_CONCAT函数解决 “数据重复、多值合并” 的问题,核心要点如下:
掌握GROUP_CONCAT后,不仅能解决 “店铺 - 设备” 的场景,还能应对 “用户 - 订单”“班级 - 学生” 等所有 “一对多” 的数据合并需求,让查询结果更简洁、更符合业务展示要求。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。