【揭秘】MySQL的find_in_set()函数使用技巧与应用场景心得总结!

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 技巧心得总结!

MySQL中的find_in_set()函数使用技巧心得与应用场景总结

🚀 个人主页 极客小俊
✍🏻 作者简介:web开发者、设计师、技术分享博主
🐋 希望大家多多支持一下, 我们一起进步!😄
🏅 如果文章对你有帮助的话,欢迎评论 💬点赞👍🏻 收藏 📂加关注

带你玩转MySQL数据库.png

前言

今天很多小伙伴来问我find_in_set这个函数在MySQL中到底有什么用处 还有与这个函数相关的应用场景会有哪些? 今天我就来给大家讲解一下这个函数从基本的使用到实际应用! 让大家不再迷茫!

1.首先认识一下find_in_set()函数

首先很多小伙伴一定会去查阅MySQL的官方手册, 但可能有些新手朋友查阅出来可能看不明白,那好吧我也先来查下手册帮助新手朋友如何来看手册中的解释: 例如下图:

1.png

官方文档解释的语法是: FIND_IN_SET(str,strlist) ;

文档解释:

(假如字符串str在由N个子链组成的字符串列表strlist 中, 则返回值的范围在 1 到 N 之间)

这句话的意思就是看str这个字符在不在或者可以说成是否包含这个strlist字符列表中, 如果有存在或包含在strlist这个字符列表中就返回一个位置的数字, 并且这个数字一定是大于0 的数字,

这里解释一下strlist字符串列表就是一个由一些被 逗号‘,’ 分开的单一字符串

注意:如果str不在strlist 或strlist 为空字符串,则返回值为 0 , 并且如任意一个参数为空,则返回值为 0 也可以说返回NULL

2.find_in_set()函数的实际基本操作

==案例1==

好了上面的解释如果还没有听明白 我们就来看看实际的操作案例吧! 打开cmd进入MySQL命令行界面, 执行如下SQL语句

SELECT FIND_IN_SET('b', 'a,b,c,d'); 
#--结果为2 , 因为b 在strlist集合中放在2的位置 并且起始数是从1开始计算起的!

如下图: 这个案例应该很简单看出这个函数的作用了吧!

不难看出只要存在于第二个字符串列中的话就返回一个位置信息!

2.png

==案例2==

select FIND_IN_SET('重庆','重庆');
#-- 这里返回的就是位置下标1

select FIND_IN_SET('重庆','北京');
#-- 这里返回的就是0  因为第一个字符串 重庆  不存在于第二个字符串当中

select FIND_IN_SET('2', '1,2'); 
#-- 这里返回的就是位置下标2

select FIND_IN_SET('6', '1'); 
#-- 这里返回的就是0  因为第一个字符串 6  不存在于第二个字符串当中

所以注意: 这时候的第二个参数的集合就有点特殊了 只有一个字符串的情况下, 如果前一个字符串 存在于在后一个字符串集合中才返回大于0的数 , 但如果不存在就会返回0

如下图:

3.png

通过案例2 小伙伴们是不是更加对find_in_set()这个函数有所了解了呢?

注意 使用find_in_set函数进行查询整张表的时候, 一次返回多条记录的情况

比如说: id是某一个表的主键字段,然后每条记录分别是id等于1,2,3,4,5的时候, 就有点类似in() 的操作了

案例:

select * from per where find_in_set(id,'2,3,4,5,6');

那么结果也就可能是这样,如下图

4.png

其实上面的SQL语句也等同于下面的in

select * from per where id in(2,3,4,5,6);

5.png

小提示: find_in_set() 一般都写在 where关键字的后面!

3.find_in_set()与in()的应用场景区别

刚才我们也看到了

select * from per where find_in_set(id,'2,3,4,5,6');
与
select * from per where id in(2,3,4,5,6);

上面两句SQL结果是一样的 ,但细心的小伙伴们不知道看出来有哪里不一样了没有呢?

对答案就在于 一个有单引号而另一个没有单引号这里也要针对你所检测的字段是数字类型 还是字符串类型的字段!

==对于find_in_set()而言==

第二个参数无论是字符串还是数字都必须用单引号括起来, 并且字符串列表是用逗号隔开,是一个字符串列表整体要是不这样写 会报语法错误!

案例

select * from per where find_in_set(id,'2,3,4,5,6');

6.png

==对于in而言==

如果是检测的字段如果是数字类型的话就不能用单引号,因为这样会让结果出现偏差

案例

select * from per where id in('2,3,4,5,6');  #--错误的

select * from per where id in(2,3,4,5,6);  #--正确的

如下图:你会看到只有一个结果为什么呢? 这是因为MySQL会自动的判断字符串的第一个是否匹配,但是后面的就截掉了 没有进行匹配!

7.png

正确的结果应该是如下

8.png

如果是检测的字符 那么每一个字符都需要用到单引号括起来 才可以, 就像下面的SQL语句, in与find_in_set()的比较 结果是一样的,

但就是要注意一下以上我所讲的注意一下数据类型细节区分问题就OK 了!

select * from per where paddr in('重庆','北京','上海'); 
#--比较
select * from per where find_in_set(paddr,'重庆,北京,上海');

9.png

首先我们新建一个表 并插入一些数据来测试! SQL代码语句如下:

CREATE TABLE `test1` (
  `id` int(8) NOT NULL auto_increment,
  `name` varchar(255) NOT NULL,
  `list` varchar(255) NOT NULL,
  PRIMARY KEY  (`id`)
);

INSERT INTO `test1`(name,list) VALUES ('张三', '篮球,足球,羽毛球');
INSERT INTO `test1`(name,list) VALUES ('李四', '射箭,跳远,足球');
INSERT INTO `test1`(name,list) VALUES ('王武', '跳远,篮球');
INSERT INTO `test1`(name,list) VALUES ('小王', '射箭');

在使用in()的时候

比如说如下SQL语句

SELECT id,name,list from test1 WHERE '篮球' IN(list);

很多人原以为可以进行这样的查询,但结果确实返回的Empty 为什么呢?

原因:

因为只有当list字段的内容完全只等于 '篮球'这个值时(和IN前面的字符串才能完全匹配),查询才有效果!

否则都得不到结果,即使'篮球'真的在list中 也不会有结果出来,这也体现了 in()对数据的精确性把控的不是很好!

也就是说 ''篮球'' 在张三、王武对应的list字段里都存在, 但就是查询不出来的原因, 就是除了''篮球' '还有其他的字符!

10.png

所以只有当list字段里面的内容完全只等于 in() 前面的字符串时 才能完全匹配,查询才有效!

如下代码

SELECT * from test1 WHERE '射箭' IN(list);

如下图:

11.png

在使用find_in_set()的时候

再比如说 我们想查询list字段中只包含篮球的数据行

SELECT id,name,list from test1 WHERE '篮球' IN('篮球','足球','羽毛球');
#-- 这里结果是全部都查询出来了 而不是我们想要对应的数据 不能正常的查询出我们想要的结果! 为什么呢?

因为这句话的意思是 查询 ''篮球'' 这个字符 在不在 这个in()所包含的字符常量里面,仅仅是如此, 然后如果成立, 有就把数据全部显示出来, select后面跟的就是 这三个字段, 前面的条件成立了 所以这三个字段的所有数据也显示出来了! 这个应该不难理解!

所以从需求语法的角度这句SQL就是不能正确给出结果的语句! 那么这样查询就显然不合理!

12.png

但我们的需求 却不是这样,我们想的是查询list字段中 只包含 '篮球',的数据行!

所以如果要让以上的SQL能正确工作,需要用find_in_set()函数

代码如下

SELECT id,name,list from test1 WHERE FIND_IN_SET('篮球',list);

13.png

小结

查字段固定的内容时候, 比如: 字段 in('篮球', '足球', '羽毛球'), 查是否有包含in中独立存在的信息 就用in

查字段的内容是否包含其中一个指定的关键内容时 ,就要用find_in_set()函数

SELECT id,name,list from test1 WHERE list in('篮球','足球'); #-- 返回list字段内容只是篮球 或 足球的数据

SELECT id,name,list from test1 WHERE find_in_set('篮球',list); #-- 返回list字段内容中包含了篮球的数据

14.png

4.find_in_set()和like的应用场景区别

在mysql中,有时我们在做数据库查询时,需要得到某字段中包含某个值的记录,但是它也不是用like能解决的,使用like可能查到我们不想要的记录,这时候mysql的FIND_IN_SET函数就派上用场了

需求案例1

我们来看下面的应用场景例子: 权限

代码案例如下

#-- 创建表并插入语句
CREATE TABLE users(
    id int(6) NOT NULL AUTO_INCREMENT,
    name VARCHAR(20) NOT NULL,
    limits VARCHAR(50) NOT NULL, -- 权限字段
    PRIMARY KEY (id)
);

INSERT INTO users(name, limits) VALUES('张三','1,2,12'); 
INSERT INTO users(name, limits) VALUES('李四','11,22,32');
INSERT INTO users(name, limits) VALUES('王武','1,2,32');

其中limits表示用户所拥有的权限(以逗号分隔)!

需求

现在想查询拥有权限编号为2的用户,则SQL查询结果如下:

SELECT * FROM users WHERE limits LIKE '%2%';

如果用like关键字的话,则查询结果如下:

15.png

这样第二条数据结果是不具有权限'2'的用户也查出来了,这种是完全不符合预期的结果!

那么现在我们利用find_in_set()函数来解决这个问题 SQL语句如下:

#-- 查询用户拥有权限编号为:2 的用户
SELECT * FROM users WHERE FIND_IN_SET(2,limits);

这样就能达到我们预期的效果,问题就解决了!

需求案例2

人有时会身兼数职,需要查找出其中担任某一职务的都有哪些人,如下面position字段,不同的职务用数字表示,多个职务以逗号隔开。其实跟上面的案例是一样的,

如下表: User信息表

16.png

需求

查找出担任1职务的人员:

如果是用模糊查询的方式 如下:

select * from 表名称 where position like '%1%'

很显然跟上面我说的也是一个道理,虽然把没有包含1的过滤掉了,仔细观察你会发现position为: '10' 的也被查出来了,但这个不符合业务要求 如下:

17.png

所以这种需求的解决方案跟上面完全一样:采用MySQL的原生函数find_in_set(str,array)来查询即可

select * from user where find_in_set(1,position);

结果如下图:

18.png

小提示 FIND_IN_SET(str,strlist)函数,其中strlist字符串列表参数只识别英文逗号, 所以小伙伴们在使用PHP 或者JAVA插入数据的时候一定要记得使用逗号把字符串分割好在保存到字段中去哦!

小结:

  1. find_in_set(str1,strlist)字符串函数是返回strlist中str1所在的位置索引, strlist必须以","分割开。

19.png

  1. like是广泛的模糊匹配,字符串中没有分隔符,

  2. find_in_set是精确匹配,字段值以英文”,”分隔,find_in_set查询的结果要比like查询更加精确!

总结

关于find_in_set()函数我就先分享到这里! 大家有问题的话可以私信 或 关注我的博客 我会尽量给大家提供解答意见!

相关实践学习
每个IT人都想学的“Web应用上云经典架构”实战
本实验从Web应用上云这个最基本的、最普遍的需求出发,帮助IT从业者们通过“阿里云Web应用上云解决方案”,了解一个企业级Web应用上云的常见架构,了解如何构建一个高可用、可扩展的企业级应用架构。
MySQL数据库入门学习
本课程通过最流行的开源数据库MySQL带你了解数据库的世界。   相关的阿里云产品:云数据库RDS MySQL 版 阿里云关系型数据库RDS(Relational Database Service)是一种稳定可靠、可弹性伸缩的在线数据库服务,提供容灾、备份、恢复、迁移等方面的全套解决方案,彻底解决数据库运维的烦恼。 了解产品详情: https://www.aliyun.com/product/rds/mysql 
相关文章
|
4月前
|
关系型数据库 MySQL 分布式数据库
安全可靠的PolarDB V2.0 (兼容MySQL)产品能力及应用场景
PolarDB分布式轻量版采用软件输出方式,能够部署在您的自主环境中。PolarDB分布式轻量版保留并承载了云原生数据库PolarDB分布式版技术团队深厚的内核优化成果,在保持高性能的同时,显著降低成本。
581 140
|
1月前
|
存储 JavaScript Java
(Python基础)新时代语言!一起学习Python吧!(四):dict字典和set类型;切片类型、列表生成式;map和reduce迭代器;filter过滤函数、sorted排序函数;lambda函数
dict字典 Python内置了字典:dict的支持,dict全称dictionary,在其他语言中也称为map,使用键-值(key-value)存储,具有极快的查找速度。 我们可以通过声明JS对象一样的方式声明dict
164 1
|
2月前
|
SQL 监控 关系型数据库
MySQL事务处理:ACID特性与实战应用
本文深入解析了MySQL事务处理机制及ACID特性,通过银行转账、批量操作等实际案例展示了事务的应用技巧,并提供了性能优化方案。内容涵盖事务操作、一致性保障、并发控制、持久性机制、分布式事务及最佳实践,助力开发者构建高可靠数据库系统。
|
3月前
|
存储 关系型数据库 MySQL
MYSQL数据加密压缩函数应用实战指南。
总的来说,加密和压缩是维护MySQL数据库中数据安全性和效率的有效手段。使用时需权衡性能与安全,合理应用加密和压缩函数。在设计数据库架构时要考虑到加密字段的查询性能,因为加密可能使得一些索引失效。压缩数据能有效减少存储空间的占用,但在服务器负载较高时应避免实时压缩和解压,以免影响总体性能。
153 10
|
5月前
|
关系型数据库 MySQL 分布式数据库
Super MySQL|揭秘PolarDB全异步执行架构,高并发场景性能利器
阿里云瑶池旗下的云原生数据库PolarDB MySQL版设计了基于协程的全异步执行架构,实现鉴权、事务提交、锁等待等核心逻辑的异步化执行,这是业界首个真正意义上实现全异步执行架构的MySQL数据库产品,显著提升了PolarDB MySQL的高并发处理能力,其中通用写入性能提升超过70%,长尾延迟降低60%以上。
|
5月前
|
SQL 关系型数据库 MySQL
MySQL 常用函数
我们这次全面梳理 MySQL 中的常用函数,涵盖 聚合函数、字符串函数、日期时间函数、数学函数 和 控制流函数 等五大类。每类函数均配有语法说明与实用示例,帮助读者提升数据处理能力,如统计分析、文本处理、日期计算、条件判断等。文章结尾提供了丰富的实战练习,帮助读者巩固和应用函数技巧,是进阶 SQL 编程与数据分析的实用工具手册。
488 2
|
8月前
|
SQL 关系型数据库 MySQL
【YashanDB知识库】MySQL field 函数的改写方法
【YashanDB知识库】MySQL field 函数的改写方法
|
8月前
|
SQL 关系型数据库 MySQL
【YashanDB知识库】MySQL field 函数的改写方法
本文来自YashanDB官网,介绍将MySQL的FIELD函数改写到YashanDB的方法。MySQL中,FIELD函数用于自定义排序;而在YashanDB中,可使用DECODE或CASE语句实现类似功能。示例展示对表`t1`按指定顺序排序的过程,提供两种改写方式,结果均符合预期。
|
8月前
|
SQL 关系型数据库 MySQL
【YashanDB知识库】MySQL的FIND_IN_SET如何在YashanDB改写
本文来自YashanDB官网,探讨了MySQL中使用`FIND_IN_SET`函数在YashanDB中不兼容的问题及解决方法。由于YashanDB的`tinyint`类型无法参与条件运算,而MySQL的Boolean类型是`tinyint`的同义词,导致直接迁移时出现错误。文章通过分析原因,提出改写方案:将`where find_in_set(`替换为`where 0 < find_in_set(`,从而实现兼容性调整,方便用户快速迁移和改写SQL语句。
|
10月前
|
SQL 关系型数据库 MySQL
Mysql-常用函数及其用法总结
以上列举了MySQL中一些常用的函数及其用法。这些函数在日常的数据库操作中非常实用,能够简化数据查询和处理过程,提高开发效率。掌握这些函数的使用方法,可以更高效地处理和分析数据。
280 19

推荐镜像

更多