MySQL基于Regexp替代多NOT LIKE实现尺寸±5匹配查询优化
MySQL REGEXP 简化查询实现方案
方案核心逻辑
完全对齐原有业务规则:逐行判断brand与title拼接生成的字符串中,不包含当前行size值上下浮动5范围内的任意整数子串,用单条正则判断替代原逻辑中11条连续的NOT LIKE链式条件,消除冗余代码。
实现原理
- 针对每行动态计算匹配范围:基于当前行的
size字段值,生成从size-5到size+5的连续整数集合 - 用正则多分支或匹配规则,将集合内的所有整数用
|连接为完整的正则匹配模式 - 利用MySQL
NOT REGEXP的语义,直接判断拼接字段不匹配该模式,即为符合要求的数据 - 因为正则未添加位置锚点,匹配逻辑与原有
NOT LIKE "%数字%"完全一致:只要数字作为任意位置的子串出现在拼接字段中,就会被正则识别命中,不会出现业务逻辑偏差
简化后的查询代码
$data = [ 'find_all_sizes' => $model ->whereRaw( "CONCAT(brand, ' ', title) NOT REGEXP CONCAT_WS('|', size - 5, size - 4, size - 3, size - 2, size - 1, size, size + 1, size + 2, size + 3, size + 4, size + 5 )" ) ->groupBy('id') ->findAll() ];
方案优势
- 代码量大幅压缩:从11条重复链式where简化为单条判断,可读性更强
- 逻辑完全对齐原有实现:针对示例表数据的返回结果和原代码100%一致
- 后续维护成本更低:如果需要调整浮动范围(比如改为上下浮动10),只需要在
CONCAT_WS的参数列表里补充对应偏移的size计算值即可,不需要增减where条件 - 不需要在PHP层预生成固定正则:因为正则模式是MySQL针对每行的size值动态计算生成的,完全适配每行不同的size场景,不会出现预生成正则和行内size不匹配的问题
- 执行效率更高:单条正则判断的执行开销远低于连续11个独立的LIKE条件遍历
注:如果后续业务需要避免数字子串误匹配(比如匹配size=5时,不把字符串中“150”里的“5”当作命中),可以在生成正则时给每个数字加MySQL支持的单词边界标识
[[:<:]]和[[:>:]],比如调整正则拼接为CONCAT_WS('|', CONCAT('[[:<:]]', size-5, '[[:>:]]'), ...)即可实现精确数字匹配。
内容的提问来源于stack exchange,提问作者seixwebdev
相关产品推荐
相关产品推荐

