Multi-Like 查询的 MySQL Regexp 解决方案

问题描述

我希望以下内容有意义。我的查询应该返回 size 列中的字符串值(+ 或 - 5)不存在于其对应的 title 列中的所有行。

表格:

 --------------
| size  | title|
 --------------
| 50    | 50ml |
| 75    | 75ml |
| 75    | 50ml |
| 100   | 97ml |
 --------------

控制器:

    $data = [
        'find_all_sizes' => $model
            ->where('CONCAT(brand," ",title) NOT LIKE CONCAT("%",size - 5,"%")')
            ->where('CONCAT(brand,size - 4,size - 3,size - 2,size - 1,size,size + 1,size + 2,size + 3,size + 4,size + 5,"%")')
            ->groupBy('id')
            ->findAll()
    ];

这很好用 - 但我猜想通过使用正则表达式可能有更好的方法,这正是我真正需要帮助的地方。

解决方法

你可以试试:

$data = [
        'find_all_sizes' => $model
            ->where("abs(size - cast(replace(title,'ml','') as signed)) < 5")
            ->groupBy('id')
            ->findAll()
    ];

在 SQL 中,假设 ml 是标题中唯一不是数字的文本,select * 查询将如下所示:

select * from t
where abs(size - cast(replace(title,'') as signed)) < 5;

+------+-------+
| size | title |
+------+-------+
|   50 | 50ml  |
|   75 | 75ml  |
|  100 | 97ml  |
+------+-------+

如果你的标题也可以包含其他字符串,你可以创建一个像这里指定的函数:How do you extract a numerical value from a string in a MySQL query? 然后运行

select * from t
where abs(size - cast(digits(title) as signed)) < 5;

你可能会逃脱惩罚

select * from t
where abs(size - cast(title as signed)) < 5;

$data = [
        'find_all_sizes' => $model
            ->where("abs(size - cast(title as signed)) < 5")
            ->groupBy('id')
            ->findAll()
    ];
,

另一个简短的回答,但有点笨拙:

WHERE 0+title BETWEEN size-5 AND size+5

在 MySQL 中,当在数字上下文中使用字符串时,将使用前导数字,其余数字将被忽略。 (没有前导数字的字符串被视为零。)

(抱歉,不需要 REGEXP。)