sql - SQL将“喜欢”更改为“包含”

标签 sql

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/

相关文章:

sql - 在 powershell 中从 System.Data.DataRow 提取数据

php - 如何使用 php 将我的 sql 查询转换为 json?

PHP/MySQL : mysqli prepared statement insert same value multiple times within for loop

mysql - COUNT(*) 和有

sql - 改变 hive 中的现有 map

mysql - 需要帮助制定 SQL 查询

mysql - 有没有办法简化下面的 mysql 查询?

sql - Select * from table where column.id is not in the other table's column1 OR column2?数据库

sql - 同一列可以对另一列有主键和外键约束吗

database - 我可以在sql查询中使用EXISTS关键字来分配结果吗