GROUP_CONCAT + IN 返回结果集只有一个??

前言

前几天在网上摸鱼,遇到了一个新鲜的 SQL 函数 GROUP_CONCAT。之前有用过,但是没有进行深入了解,这次索性就记录一下。

快速入门

GROUP_CONCAT 函数用于将多行数据按照指定的顺序连接成一个字符串。

sql 复制代码
SELECT GROUP_CONCAT(id) FROM `tb_park` WHERE merchant_id=1;

-- 2,3,1

配合 ORDER BY:有序连接

默认情况下,GROUP_CONCAT 函数返回的字符串是 无序的,但是我们可以通过使用 ORDER BY 子句来指定排序规则。

特别注意

在 ORDER BY 子句中 只能使用被连接的列名,不能使用其他列名。

sql 复制代码
SELECT GROUP_CONCAT(id ORDER BY id) FROM `tb_park` WHERE merchant_id=1;

-- 1,2,3

配合 SEPARATOR:指定分隔符

通过使用 SEPARATOR 关键字,可以指定连接后的字符串中的分隔符。

sql 复制代码
SELECT GROUP_CONCAT(id ORDER BY id SEPARATOR '-') FROM `tb_park` WHERE merchant_id=1;

-- 1-2-3

配合 GROUP BY:分组连接

GROUP_CONCAT 函数通常与 GROUP BY 子句一起使用,以便在对结果进行分组时,将每个分组内的值连接成一个字符串。

sql 复制代码
SELECT GROUP_CONCAT(id ORDER BY id) FROM `tb_park` GROUP BY merchant_id;

-- 1,2,3
-- 4,6,8,10,11,12

GROUP_CONCAT + IN 配合使用

那么,现在 GROUP_CONCAT 配合 IN 使用,结果将如何呢?

sql 复制代码
SELECT GROUP_CONCAT(id) FROM `tb_park` WHERE merchant_id=1;

-- 2,3,1
sql 复制代码
SELECT * FROM tb_road_berth_state WHERE park_id IN (
    SELECT GROUP_CONCAT(id) ids FROM `tb_park` WHERE merchant_id=1
);

-- 但是,结果只有 park_id=2,这是为什么???

但是呢,结果集只有 park_id=2 的,这是为什么???

分析原因

这是因为 GROUP_CONCAT 生成的是一个 字符串 ,其中包含了多个值,格式为 '2,3,1'

而 IN 子句期望的是单个值或者一个值列表,格式为 2,3,1

解决方案

要解决这个问题,你可以尝试在 GROUP_CONCAT 函数生成的字符串中使用 FIND_IN_SET 函数,以便将多个值与 IN 子句中的单个值进行比较。

sql 复制代码
SELECT * FROM tb_road_berth_state WHERE FIND_IN_SET(
    park_id, 
    (SELECT GROUP_CONCAT(id) ids FROM `tb_park` WHERE merchant_id=2)
) >0;

-- 完美解决

FIND_IN_SET 函数

如何使用

FIND_IN_SET 函数用于在逗号分隔的字符串列表中查找某个值,并返回其在列表中的位置。该函数的语法如下:

sql 复制代码
FIND_IN_SET(search_value, target_string)

其中,search_value 是要查找的值,target_string 是逗号分隔的字符串列表。

FIND_IN_SET 函数的工作原理是,它会在 target_string 中查找 search_value,并返回其在逗号分隔列表中的位置。如果找到了匹配的值,就会返回其位置;如果没有找到匹配的值,就会返回 0。

以下是一个示例,演示了 FIND_IN_SET 函数的用法:

sql 复制代码
SELECT FIND_IN_SET('b', 'a,b,c,d');

在这个示例中,FIND_IN_SET 函数会在逗号分隔的字符串列表 'a,b,c,d' 中查找 'b',并返回其在列表中的位置,即 2。

对性能方面有没有影响?

使用 FIND_IN_SET 函数可能会对查询性能产生一定的影响,特别是在大型数据集上。这是因为 FIND_IN_SET 函数需要对逗号分隔的字符串列表进行解析和比较,这可能会导致一些额外的计算开销。

另外,FIND_IN_SET 函数在某些情况下可能无法有效地利用索引,尤其是在大型表上。这可能会导致查询性能下降,特别是在需要频繁执行这类查询时。

为了最大程度地减少性能影响,可以考虑以下几点:

  • 确保表上的相关列有适当的索引,以便数据库可以更有效地处理FIND_IN_SET函数。
  • 限制FIND_IN_SET函数生成的字符串长度,避免生成过长的字符串。
  • 定期进行数据库性能优化和索引优化,以确保数据库能够高效地处理这类查询。

总的来说,使用 FIND_IN_SET 函数可能会对查询性能产生一定的影响,但在大多数情况下,这种影响是可以接受的。重点是根据具体情况进行优化,以确保查询能够以最佳性能运行。

写在最后

为了性能考虑,还是老老实实地使用 JOIN 语法吧,别整这些花活!!!

相关推荐
我是一颗柠檬3 小时前
【MySQL全面教学】MySQL基础SQL语句Day3(2026年)
数据库·后端·sql·mysql·oracle
MandalaO_O4 小时前
MyBatis 与 MySQL 执行流程
数据库·mysql·mybatis
键盘上的猫头鹰5 小时前
【从零学MySQL(三)】数据增删改(DML)及 SELECT 查询详解
数据库·mysql·数据分析
Cry丶6 小时前
WebFlux + R2DBC 场景下的分库分表预研:从架构选型到落地风险
mysql·postgresql·数据库架构·shardingsphere·分库分表·webflux·r2dbc
键盘上的猫头鹰6 小时前
【从零学MySQL(二)】数据库基础操作、数据类型与约束(附Navicat演示)
数据库·mysql·数据分析·数据可视化
阮胜昌8 小时前
在CentOS 7.9上安装MySQL8.4.4 LTS
mysql·mysql8.4
码上谈兵9 小时前
一次 MySQL 连接池打满,我花一晚上重构了 Go 的数据库操作
mysql
夕除10 小时前
spring boot 13
java·mysql·spring
WAIT_TIME10 小时前
基于 Docker 快速构建 MySQL InnoDB Cluster 高可用集群与 Router 读写分离
mysql·docker·集群·innodb cluster