SQL如何基于指定关键词表过滤忽略目标数据行
问题说明
需求是根据表2存储的关键词,过滤表1中关键词和其他字符连写、无空格分隔的行(即原数据第2、3行),仅保留关键词作为独立单词存在的记录。
两张表的测试数据如下:
- 表1(
base_tbl):
| No | Name |
|---|---|
| 1 | kumar unknow raja |
| 2 | kumarunknowraja sameple |
| 3 | kumartradraja testing |
| 4 | kumar trad raja |
| 5 | trad |
| 6 | unknow |
- 表2(
exc_tbl,待匹配关键词表):
| Name |
|---|
| unknow |
| trad |
当前使用的查询语句返回了全部记录,未达到过滤效果,语句如下:
select * from base_tbl where exists (select name from exc_tbl);
问题原因
原语句不生效的核心原因:
exists子查询未设置两表的关联匹配规则,只要exc_tbl内有数据,exists判断结果就恒为真,相当于没有加过滤条件,自然返回主表全部记录。- 未实现「独立单词匹配」逻辑,无法区分关键词是单独成词,还是和其他字符连写在同一个字符串片段中。
实现方案
通用兼容写法(适配绝大多数关系型数据库):通过给字段值前后拼接空格的方式,保证匹配到的关键词一定是被空格/字符串边界包裹的独立单词,不会命中连写的字符片段:
SELECT DISTINCT b.* FROM base_tbl b INNER JOIN exc_tbl e ON CONCAT(' ', b.Name, ' ') LIKE CONCAT('% ', e.Name, ' %');
逻辑说明:将base_tbl的Name字段前后各拼接一个空格,再匹配前后带空格的关键词,比如:
- 对
kumartradraja testing,拼接后为kumartradraja testing,不存在trad这个被空格包裹的片段,会被过滤 - 对
kumar trad raja,拼接后为kumar trad raja,存在trad片段,会被保留 - 对单独的
trad,拼接后为trad,也能正常匹配保留
如果使用MySQL,也可以用单词边界正则实现,写法更简洁:
SELECT DISTINCT b.* FROM base_tbl b INNER JOIN exc_tbl e ON b.Name REGEXP CONCAT('[[:<:]]', e.Name, '[[:>:]]');
其中[[:<:]]和[[:>:]]是MySQL内置的单词边界匹配符,效果和上述拼接空格的写法完全一致。
执行结果
上述语句执行后返回如下记录,已正确过滤第2、3行的连写数据,符合预期:
| No | Name |
|---|---|
| 1 | kumar unknow raja |
| 4 | kumar trad raja |
| 5 | trad |
| 6 | unknow |
内容的提问来源于stack exchange,提问作者Vinoth_S
相关产品推荐
相关产品推荐

