当前位置:首页 > 娱乐

sqlsever模糊查找几十个关键字

有人问我,模糊SQL Server里怎么一次模糊匹配几十个关键字。查找他手里有个客户名单,个关想把备注字段里带“退费”“投诉”“差评”“曝光”这类词的键字记录全捞出来。一个LIKE一个LIKE地OR下去,模糊写了二十几行,查找眼睛都花了。个关

这事其实有更省力的键字写法。核心就一句:把关键字塞进一张临时表或表变量,模糊然后跟目标表做CROSS APPLY,查找配合CHARINDEX或LIKE判断。个关

先看最直观的键字笨办法。假设关键字就五个,模糊你可以这么写:

SELECT * FROM 客户表 WHERE 备注 LIKE '%退费%' OR 备注 LIKE '%投诉%' OR 备注 LIKE '%差评%' OR 备注 LIKE '%曝光%' OR 备注 LIKE '%举报%';

五个还行,查找五十个呢?个关写出来像一条蜈蚣,维护起来要命。加一个词就得改SQL,改完还得测。

换个思路。建个表变量存关键字:

DECLARE @kw TABLE (word NVARCHAR(50)); INSERT INTO @kw VALUES (N'退费'),(N'投诉'),(N'差评'),(N'曝光'),(N'举报'), (N'维权'),(N'退款'),(N'欺诈'),(N'虚假'),(N'拖延');

然后这样查:

SELECT DISTINCT c.* FROM 客户表 c CROSS APPLY (SELECT word FROM @kw) k WHERE c.备注 LIKE '%' + k.word + '%';

五十个关键字也就是往@kw里多插几行的事。SQL主体一个字不用动。

这里有个细节要注意。CROSS APPLY在关键字表没索引的情况下,实际执行计划可能走嵌套循环,每行备注都要跟所有关键字比对一遍。数据量小无所谓,几十万行以上就得掂量一下。我试过在80万行的表上跑30个关键字,全表扫描加嵌套循环,跑了将近40秒。后来把关键字表换成临时表并加了索引,时间降到6秒左右。差别就在这儿。

用CHARINDEX也行,写法差不多:

SELECT DISTINCT c.* FROM 客户表 c CROSS APPLY (SELECT word FROM @kw) k WHERE CHARINDEX(k.word, c.备注) > 0;

CHARINDEX和LIKE在模糊匹配上性能接近,但CHARINDEX写起来更灵活,比如你想返回命中的是哪个关键字:

SELECT c.客户ID, c.备注, k.word AS 命中关键字 FROM 客户表 c CROSS APPLY (SELECT word FROM @kw) k WHERE CHARINDEX(k.word, c.备注) > 0;

这个结果集直接告诉你每条记录踩了哪个词,后续分类处理很方便。

还有一种场景是关键字本身就带通配符,比如“退%费”。那就别用CHARINDEX了,只能LIKE。但LIKE的前缀如果是通配符开头,索引基本废掉,全表扫描跑不掉。几十个关键字同时扫,CPU和IO都会飙。这时候可以考虑全文索引。SQL Server的全文索引对多关键字模糊匹配支持得不错,CONTAINS和FREETEXT都能用。但全文索引的配置和维护有额外成本,小项目犯不上。

我的习惯是:关键字少于20个、表小于50万行,直接用表变量+CROSS APPLY+CHARINDEX,够用。超过这个量级,要么上临时表加索引,要么把匹配逻辑挪到应用层做。别硬扛。

另外提醒一句,关键字里如果有单引号,插入@kw的时候要转义,写成两个单引号。这个坑我踩过,报错信息看得人一头雾水。

最后说个实际案例。之前帮一个电商团队处理售后备注,关键字有60多个,分“退款类”“质量类”“物流类”“服务类”四组。他们原来是用四个独立查询分别跑,再UNION ALL。改成一张关键字表加个分类字段,一次查询出结果,按分类GROUP BY,代码从200多行缩到30行。维护的时候加词改词就在INSERT里动,不用碰查询逻辑。这才是表驱动该有的样子。

分享到: