问题描述
我希望以下内容有意义。我的查询应该返回 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。)