products table (mySQL)
record_id categories (comma-delimited list)
--------- --------------------------------
1 960|1,957|1,958|1
我有以下动态查询(为此问题简化了此查询)。该查询传递给指定类别,每个类别均采用xxxx | yyyy格式,我需要返回以逗号分隔的类别列表中具有传递类别的产品。
当前查询如下:
select p.* from products p
where (p.categories like '%27|0%' or p.categories like '%972|1%' or p.categories like '%969|1%')
但是,LIKE子句有时允许出现异常。
我想更像写查询:
select p.* from products p
where (p.categories contains '27|0' or p.categories contains'972|1' or p.categories contains '969|1')
我该怎么做?
最佳答案
您可以使用LOCATE函数:
select p.* from products p
where (LOCATE('27|0', p.categories) > 0 or LOCATE('972|1', p.categories) > 0 or LOCATE('969|1', p.categories) > 0))
编辑:如果要避免误报,可以将条件数量加倍,如果第二个数字可以是该类别的第一个数字,则可以加倍三倍的条件:
select p.* from products p
where (
LOCATE('27|0', p.categories) = 1 or LOCATE(',27|0', p.categories) > 0 or
LOCATE('972|1', p.categories) = 1 or LOCATE(',972|1', p.categories) > 0 or
LOCATE('969|1', p.categories) = 1 or LOCATE(',969|1', p.categories) > 0
)
EDIT2:最终解决方案(很长一段时间,知道逗号是分隔符之后):
select p.* from products p
where (
p.categories = '27|0' OR LOCATE('27|0,', p.categories) = 1 or LOCATE(',27|0,', p.categories) > 0 or LOCATE(',27|0', p.categories) = CHAR_LENGTH(p.categories) - CHAR_LENGTH(',27|0') + 1 or
p.categories = '972|1' OR LOCATE('972|1,', p.categories) = 1 or LOCATE(',972|1,', p.categories) > 0 or LOCATE(',972|1', p.categories) = CHAR_LENGTH(p.categories) - CHAR_LENGTH(',972|1') + 1 or
p.categories = '969|1' OR LOCATE('969|1,', p.categories) = 1 or LOCATE(',969|1,', p.categories) > 0 or LOCATE(',969|1', p.categories) = CHAR_LENGTH(p.categories) - CHAR_LENGTH(',969|1') + 1
)
替代方法(更短,使用REGEX,可能更慢)
select p.* from products p WHERE
p.categories REGEXP '(,|^)27\|0(,|$)'
or p.categories REGEXP '(,|^)972\|1(,|$)'
or p.categories REGEXP '(,|^)969\|1(,|$)'
您将需要逃脱| REGEXP的字符,因为这是正则表达式中的特殊字符。
编辑3:
REGEXP解决方案可以通过仅使用一个正则表达式来改进,此类表达式在查询期间进行编译,因此即使匹配表达式更复杂,单个编译也比3个单独的编译要快:
select p.* from products p WHERE p.categories REGEXP '(,|^)(27\|0|972\|1|969\|1)(,|$)'
关于sql - SQL将“喜欢”更改为“包含”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4633626/