我的表看起来像这样:
id | title | tags
1 | I like things | 9,3,7,10
2 | Stuff about i | 12,3,7,10
3 | Overly loaded | 1,3,4,5
4 | Never ever AT | 12,10
4 | Forever alone | 9
注意:这些名称已经完成,它们仅用于说明目的
关于标签的事情:
0
到12
1
,9
和12
将始终是此列表中的第一个标记,其后是从低到高的排序顺序的其余标记1
,9
或12
。我想添加一个过滤器功能,允许用户使用这些标签过滤列表。让我们忽略客户端部分,只关心我们收到的内容。
假设脚本收到以下输入(始终排序):"3,4,9"
然后,我想将此传递给MySQL查询以检索匹配的项目。该网站也有一个分页功能,但我只是这样说,因为它可能会影响语句的顺序,否则它并不重要。它只是在最后添加了LIMIT
语句。
放弃所有转义和不放弃的内容,我尝试使用的查询是
SELECT * FROM `$tablename` WHERE tags LIKE '%$input%' ORDER BY title ASC LIMIT 0,10
但这 - 当然 - 没有用。我给了我这个不错的小错误信息,说:
您的SQL语法有错误;检查与MySQL服务器版本对应的手册,以便在 script.php 的第1行''%3,4,9%'附近使用ORDER BY标题ASC LIMIT 0,10'附近使用正确的语法在线 n
我想知道如何更改此查询以便能够正确过滤结果,即使它需要额外的功能来将多个LIKE
语句附加在一起。
答案 0 :(得分:3)
WHERE tags LIKE '%$input%'
仅在标签字符串中找到输入标签列表时才有效。 “3,4,9”不像“3,4,5,9”
你有一个非规范化的结构,这会导致你的问题,你应该实现每个标签值一行。
另一种方法是拆分输入字符串并使用多个OR LIKE
语句:
WHERE tags LIKE '%input1%'
OR tags LIKE '%input2%'
....
然后你必须处理1
与11
匹配的问题,这意味着在LIKE
语句的每一侧的正面和背面连接逗号,或者填充一些值。解决方法变成了一个丑陋的野兽,其效率远低于修复底层设计问题。
答案 1 :(得分:2)
我知道这不会是公认的答案,但是因为可能会出现无法改变数据库结构的情况,我想我会把它作为问题的精确答案。
考虑到你所说的限制,假设PHP是你的控制语言(因为这个问题是用PHP标记的),我会用PHP构建SQL语句:
<?php
// assuming $tags contains your comma-delimited tags
$tags_array = explode(',',$tags);
$where = 'where true';
for($i=0;$i<sizeof($tags_array);$i++) {
switch($tags_array[$i]) {
case '1':
$where .= " and tags LIKE '1%' and tags NOT LIKE '12%'";
break;
case '9':
case '12':
$where .= " and tags LIKE '" . $tags_array[$i] . "%'";
break;
default:
$where .= " and tags LIKE '%," . $tags_array[$i] . "%'";
break;
}
}
$sql = "SELECT * FROM `$tablename` " . $where . " ORDER BY title ASC LIMIT 0,10";
?>
话虽如此,我同意上面评论的每个人:在数据库中正确地获取数据模型要好得多。