MYSQL ORDER BY与WHERE子句中的值数组

时间:2012-09-09 02:04:01

标签: 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<>" " 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正常工作。 ORDER BY的目的是将查询结果从搜索字符串上的大多数命中顺序排列到最小。我的假设是我在某种程度上需要在ORDER BY子句中再次遍历数组,但我不确定如何执行此操作或者我是否在该假设中是正确的。那里有帮助吗?

我知道我可以使用mysql全文搜索更简单,但正在使用的表是InnoDB,所以我不认为这是一个选项。

2 个答案:

答案 0 :(得分:0)

要考虑的几个问题......

1)ORDER BY表达式中的任何列tag1,tag2,tag3 ...中的NULL值将为整个表达式返回NULL。考虑:

SELECT 0 + NULL + 1 + 0 

如果所有这些列都定义为NOT NULL,那么这不是问题。但更一般地说,你想要从NULL值绝缘......

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)您的查询中需要GROUP BY q_id的原因并不清楚。


我建议您通过获取ORDER BY子句中的表达式进行测试,并将其复制到SELECT列表中,然后运行查询以查看它返回的值。

在MySQL中,如果将该表达式添加到SELECT列表并为其指定别名,则可以在ORDER BY上引用别名。

 SELECT expr AS match_count, ...
   FROM
  ORDER BY match_count DESC

答案 1 :(得分:0)

您正在寻找的功能 - 搜索多列搜索字词并按相关性排序 - 正是full-text search的设计目标。如果可能的话,你应该使用它,因为它可以减少你的长期头痛。

如果您绝对必须以这种方式实现,那么有必要将 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

然后,只选择匹配项,您可以使用HAVING relevance > 0。要订购,您只需使用ORDER BY relevance DESC(因为上面的相关性列会为您提供匹配列数的计数)。