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

作者:极客小俊 一个专注于web技术的80后
我不用拼过聪明人,我只需要拼过那些懒人 我就一定会超越大部分人!
@极客小俊,简书官方首发原创文章
企业博客: 👉 GeekerJun 👈
个人博客 : 👉 cnblogs.com 👈

在这里插入图片描述

前言

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

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

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

在这里插入图片描述

官方文档解释的语法是: 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

如下图:

在这里插入图片描述

通过案例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');

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

在这里插入图片描述

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

select * from per where id in(2,3,4,5,6);
在这里插入图片描述

小提示: 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');
在这里插入图片描述

==对于in而言==

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

案例

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

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

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

6.png

正确的结果应该是如下

在这里插入图片描述

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

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

select * from per where paddr in('重庆','北京','上海'); 
#--比较
select * from per where find_in_set(paddr,'重庆,北京,上海');
在这里插入图片描述

首先我们新建一个表 并插入一些数据来测试! 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字段里都存在, 但就是查询不出来的原因, 就是除了''篮球' '还有其他的字符!

在这里插入图片描述

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

如下代码

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

如下图:


在这里插入图片描述

在使用find_in_set()的时候

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

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

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

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

在这里插入图片描述

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

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

代码如下

SELECT id,name,list from test1 WHERE FIND_IN_SET('篮球',list);
11.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字段内容中包含了篮球的数据

在这里插入图片描述

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关键字的话,则查询结果如下:

在这里插入图片描述

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

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

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

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

需求案例2

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

如下表: User信息表


在这里插入图片描述

需求

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

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

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

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

在这里插入图片描述

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

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

结果如下图:

16.png

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

小结:

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


    在这里插入图片描述
  2. like是广泛的模糊匹配,字符串中没有分隔符,

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

总结

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

end.jpg
bilibili_gif.gif

如果我的博客对你有帮助、如果你喜欢我的博客内容,请 “点赞” “评论” “收藏” 一键三连哦!


如果以上内容有任何错误或者不准确的地方,欢迎在下面 👇 留个言指出、或者你有更好的想法,欢迎一起交流学习

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,884评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,755评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,369评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,799评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,910评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,096评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,159评论 3 411
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,917评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,360评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,673评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,814评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,509评论 4 334
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,156评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,882评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,123评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,641评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,728评论 2 351

推荐阅读更多精彩内容