为了账号安全,请及时绑定邮箱和手机立即绑定

Mysql中FIND_IN_SET与JOIN在一对多关系查询时的优劣

Mysql中FIND_IN_SET与JOIN在一对多关系查询时的优劣

慕森卡 2019-03-29 10:58:19
Mysql中的FIND_IN_SET函数在我知道它之前,我在做一个一对多的外键查询时,都会在中间设计一个关系表。比如一篇文章(post)对应多个标签(tag),我就会在中间设计一个关系表(post_tag_mapping)来记录文章和标签的对应关系,然后查询某一个标签下的文章时,就用JOIN语句来实现了,这也应该是处理一对多关系查询时的标准做法。一般语句就像下面SELECT*FROMpostLEFTJOINpost_tag_mappingWHEREtag_id=123但是当我发现FIND_IN_SET函数后,就可以完全不用JOIN这种查询方式了,我们完全可以在文章表里设置一个类型为SET的标签字段(tags),它存储标签id的格式就像这样111,222,333,查询语句就变成了SELECT*FROMpostWHEREFIND_IN_SET('123',tags)不用做连接查询了,我不知道这两者在查询效率上哪个更占优势?他们的应用场景有什么需要注意的地方?SET类型能够做索引吗,做完以后对FIND_IN_SET有用吗?
查看完整描述

2 回答

?
精慕HU

TA贡献1845条经验 获得超8个赞

就你的例子来说,用中间(映射)表,可以借助索引提高查询效率。FIND_IN_SET属于字符串操作,如果用在字段上,得全表扫描。SET类型的实现是64位的bitmap(对应64个成员),作为FIND_IN_SET的第二个参数,可以用位运算来提高函数的效率(不等于查询效率)。限制有:成员不能包含“,”字符最多只能有64个成员,而且需要预定义,所以用来做tag不合适即便加索引也是整体的(即64个位对应的组合状态),而不能针对某一个成员(某一个位)UPDATE操作也是整体的,你需要自己运算新的bitmap所以SET最适合用于值域小,取值固定,整体查询的状态集合。比如记录某人去过中国哪些省:可以直接比较两个人是否去过相同的省份,或者直接获得差别,可以高效地查询哪些人只去过某省或某些省,但查哪些人去过某省或某些省依然是扫全表。
                            
查看完整回答
反对 回复 2019-03-29
?
慕后森

TA贡献1802条经验 获得超5个赞

语法:
FIND_IN_SET(str,strlist)返回str在strlist(1~N个以逗号分割的字符串)中的位置(1~N)。
selectFIND_IN_SET('dell','apple,thinkpad,dell')ASFIND;
FIND3
str不在strlist中或者strlist为空时返回0
selectFIND_IN_SET('acer','apple,thinkpad,dell')ASFIND
FIND0
selectFIND_IN_SET('acer','')ASFIND
FIND0
存在参数为NULL时返回NULL
selectFIND_IN_SET('acer',NULL)ASFIND
FINDNULL
selectFIND_IN_SET(NULL,'apple,thinkpad,dell')ASFIND
FINDNULL
selectFIND_IN_SET(NULL,NULL)ASFIND
FINDNULL
如果第一个参数为数字类型:
selectFIND_IN_SET('001','003,001,002')ASFIND
FIND2
selectFIND_IN_SET(001,'003,001,002')ASFIND
FIND0
selectFIND_IN_SET(001,'003,1,002')ASFIND
FIND2
                            
查看完整回答
反对 回复 2019-03-29
  • 2 回答
  • 0 关注
  • 2360 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信