mysql sql多个like性能_sql 多个模糊查询优化

目前在做“Brick4.com - 国产积木索引表”这个小工具。它是当作“工具书”而存在的,必然需要一个靠谱的检索功能。按主题和品牌这些即有的筛选就不说了,今天把我的摸索过程整理一下,说说如何用 MySQL 实现多关键词站内“模糊查找”。

拿一个简化的小表儿做例子

表名叫:article

字段有:title、subtitle、tag、text……

涉及到查找的字段有三个:title、subtitle、tag

像我这种初学者,首先想到的肯定是 LIKE ,关键词是“车”的话,就这样:

SELECT * FROM article WHERE

title LIKE "%车%"

OR subtitle LIKE "%车%"

OR tag LIKE "%车%"

怎么样?LIKE 是万能的,用一个 LIKE 解决不了的事情就多用几个 LIKE 。于是多关键词就这样搞:

SELECT * FROM article WHERE

(

title LIKE "%车%"

OR subtitle LIKE "%车%"

OR tag LIKE "%车%"

) OR (

title LIKE "%摩托%"

OR subtitle LIKE "%摩托%"

OR tag LIKE "%摩托%"

) OR (

title LIKE "%红色%"

OR subtitle LIKE "%红色%"

OR tag LIKE "%红色%"

) OR (

title LIKE "%美国%"

OR subtitle LIKE "%美国%"

OR tag LIKE "%美国%"

) OR (

title LIKE "%2006%"

OR subtitle LIKE "%2006%"

OR tag LIKE "%2006%"

)

虽然很工整,不过能不能简洁一点?当然行!看我变形!我们可以用正则:

SELECT * FROM article WHERE

title REGEXP "车|摩托|红色|美国|2006"

OR subtitle REGEXP "车|摩托|红色|美国|2006"

OR tag REGEXP "车|摩托|红色|美国|2006"

怎么样?意外不意外?惊喜不惊喜?其实咱们还可以更进一步,把几个字段合并起来:

SELECT * FROM article WHERE

CONCAT_WS(" ", title, subtitle, tag) REGEXP "车|摩托|红色|美国|2006"

这一句话,和前面洋洋洒洒那一大坨是等同的。

之所以用 CONCAT_WS() 而不是 CONCAT() ,是因为后者在某字段为 NULL 的情况下会导致合并结果为 NULL,万无一失嘛,我们用前者。

要求不高的话,到这其实就可以了。但是总感觉找到的文章似有关联又东一榔头西一杵,所以咱们要排序。我希望“按照匹配关键词的多寡来排序”,匹配关键词越多的文章越靠前,咋办呢?

SELECT *,

(

(IF( CONCAT_WS(" ", title, subtitle, tag) LIKE "%车%", 1, 0))

+ (IF( CONCAT_WS(" ", title, subtitle, tag) LIKE "%摩托%", 1, 0))

+ (IF( CONCAT_WS(" ", title, subtitle, tag) LIKE "%红色%", 1, 0))

+ (IF( CONCAT_WS(" ", title, subtitle, tag) LIKE "%美国%", 1, 0))

+ (IF( CONCAT_WS(" ", title, subtitle, tag) LIKE "%2006%", 1, 0))

) AS keyweight

FROM article WHERE

CONCAT_WS(" ", title, subtitle, tag) REGEXP "车|摩托|红色|美国|2006"

ORDER BY keyweight DESC

“通过一组关键词站内模糊搜索,按照匹配关键词的多寡来排序。”这个需求,目标达成!撒花撒花~

最终的语句扔在这里,相信你一看就懂了。关键是思路,我可是沥沥拉拉摸索了好几天啊……

在今天的例子里 title、subtitle、tag 三个字段同等重要,所以直接合并起来,如果你希望有权重的概念,比如 主标题 大于 副标题 大于 标签,思考一下,其实也不复杂。

最后再打个广告:Brick4.com - 最实用的国产积木索引表 更好用了!感兴趣的小伙伴快来支持一下!!

2017-09-13 更新

发现 Brick4 搜索的关键词开始区分大小写了。探究源头是因为最近把一个数据类型为 INT 的字段纳入了检索,区分大小写正是因此造成的。

举个例子,比如 time 的数据类型是数字,title 是文本,直接这样写就会区分大小写:

SELECT * FROM article WHERE

CONCAT_WS("", time, title) REGEXP "关键词"

要是把数字转成字符串再拼合就没事了:

SELECT * FROM article WHERE

CONCAT_WS("", CHAR(time), title) REGEXP "关键词"

上述转自:

http://lao.si/120============================================================================

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值