MYSQL ORDER BY在WHERE子句中包含一个值数组
我正在处理一个搜索脚本的一部分,其中提交的搜索字符串被解析,每个重要的词被放入一个数组中。然后在WHERE子句中循环该数组以搜索MYSQL数据库中的多个列。下面是一个示例SQL代码:MYSQL ORDER BY在WHERE子句中包含一个值数组,mysql,sql,arrays,sql-order-by,Mysql,Sql,Arrays,Sql Order By,我正在处理一个搜索脚本的一部分,其中提交的搜索字符串被解析,每个重要的词被放入一个数组中。然后在WHERE子句中循环该数组以搜索MYSQL数据库中的多个列。下面是一个示例SQL代码: $sql = "SELECT title, question, tag1, tag2, tag3, tag4, tag5 FROM question WHERE "; while(list($key,$val)=each($split_stemmed)){ if($val<>" "
$sql = "SELECT title, question, tag1, tag2, tag3, tag4, tag5 FROM question WHERE ";
while(list($key,$val)=each($split_stemmed)){
if($val<>" " and strlen($val) > 0){
$sql .=
"(title LIKE '$val%'
OR question LIKE '$val%'
OR tag1 LIKE '$val%'
OR tag2 LIKE '$val%'
OR tag3 LIKE '$val%'
OR tag4 LIKE '$val%'
OR tag5 LIKE '$val%') OR";
}
}
$sql=substr($sql,0,(strLen($sql)-3));
$sql .= "GROUP BY q_id ORDER BY
((title LIKE '$val%') +
(question LIKE '$val%') +
(tag1 LIKE '$val%') +
(tag2 LIKE '$val') +
(tag3 LIKE '$val%') +
(tag4 LIKE '$val%') +
(tag5 LIKE '$val%')) desc, title asc";
我遇到的问题是如何使订单正常工作。ORDER BY的目的是将查询结果从搜索字符串中点击次数最多的顺序排列到点击次数最少的顺序。我的假设是,我需要以某种方式在ORDERBY子句中再次循环数组,但不确定如何执行此操作,或者我的假设是否正确。有帮手吗
我知道我可能可以使用mysql全文搜索来简化这个过程,但是使用的表是InnoDB,所以我认为目前还不能这样做有几个问题需要考虑……p> 1任何列tag1、tag2、tag3中的空值。。。在ORDER BY中,表达式将为整个表达式返回NULL。考虑:
SELECT 0 + NULL + 1 + 0
如果所有这些列都定义为NOTNULL,那么这不是问题。但更一般地说,您希望与空值隔离
ORDER BY ( IFNULL(title LIKE '$val%'),0) +
IFNULL(question LIKE '$val%'),0) +
IFNULL(tag1 LIKE '$val%'),0) +
IFNULL(tag2 LIKE '$val' ),0) +
-或者-
ORDER BY ( IFNULL(title ,'') LIKE '$val%') +
IFNULL(question,'') LIKE '$val%') +
IFNULL(tag1 ,'') LIKE '$val%') +
IFNULL(tag2 ,'') LIKE '$val' ) +
)
根据模式,tag2上似乎缺少了一个%,但完全可能是故意遗漏的
2根本不清楚为什么在查询中需要按q_id分组
我建议您通过在ORDERBY子句中获取表达式进行测试,并将其复制到SELECT列表中,然后运行查询以查看返回的值
在MySQL中,如果将该表达式添加到SELECT列表并为其指定别名,则可以引用ORDER BY上的别名
SELECT expr AS match_count, ...
FROM
ORDER BY match_count DESC
您正在寻找的功能—搜索多个列中的搜索词并按相关性排序—正是为其设计的。如果可能的话,你应该使用它,因为从长远来看,它会减少你的头痛 如果您必须以这种方式实现,那么有必要将LIKE语句移动到SELECT子句中,以便对它们求和。像这样:
SUM (CASE WHEN title LIKE '$val%' THEN 1 ELSE 0 END
+ CASE WHEN question LIKE '$val%' THEN 1 ELSE 0 END
+ CASE WHEN tag1 LIKE '$val%' THEN 1 ELSE 0 END
... etc
) AS relevance
然后,要仅选择匹配项,可以使用相关性>0。要排序,您只需使用“按相关性说明排序”,因为上面的“相关性”列将为您提供匹配列数。为什么有多个标记列?发布到站点的每个问题都可以有多个与之关联的描述性标记。@Cbomb请查看数据库的规范化。这会让你的生活轻松14%。你不会用类似的语句来点菜。您可以按特定的内容排序,例如表中的列或SELECT语句。如果您还需要其他东西,请使用订单中的案例。你的问题应该只基于SQL,PHP的东西应该被删除;问题不是关于PHP,而是一个SQL问题。PHP代码只是让问题更难阅读和回答。请使用全文搜索,你在这里发明轮子。谢谢你的回答。我会尽快测试这个。至于全文搜索,我已经读到,就MYSQL而言,您只能在MYISAM表中使用FTS,尽管可能很快也会在InnoDB中使用FTS,而且MYISAM有很多缺点,不值得使用。你认为这是正确的信息吗?@Cbomb老实说,我不知道MYISAM和InnoDB的优劣。虽然,从5.6版开始,这两个版本都得到了支持:哦,哇,是的,MyISAM听起来不太好。。。没有交易?没有外键支持???我试着测试这些可能的解决方案,但似乎没有任何效果。由于有很多关于全文搜索的建议,我决定放弃这项工作,而不是试图重新发明轮子,我打算使用Sphinx作为我的搜索引擎。希望这会很好。我会尽快测试。谢谢。