【问题标题】:How to sort MySQL results by most matches when using LIKE使用 LIKE 时如何按大多数匹配对 MySQL 结果进行排序
【发布时间】:2014-10-02 10:10:49
【问题描述】:

我目前正在处理一个查询,该查询必须显示特定表中所有文章的列表,但它必须根据搜索表单对列表进行排序,以便首先显示包含最多/最佳匹配的文章,然后那些根本没有任何匹配项的将按字母顺序显示在最后。

我制作的这段代码运行良好,但我找不到按最多匹配/相关性对匹配项进行排序的方法。

这是我的代码:

$search = $_POST["searhwords"];
$search = preg_replace('/\s+/', ' ',$search);

$SearchQueryArray = str_replace(",", "", $search);
$SearchQueryArray = str_replace(" ", ",", $SearchQueryArray);
$SearchQueryArray = explode(',', $SearchQueryArray);


$outputtt1 = '';
$outputtt2 = '';
foreach ( $SearchQueryArray as $queryword )
{
    $outputtt1 .= "title LIKE '%".$queryword."%' OR ";  
    $outputtt2 .= "title NOT LIKE '%".$queryword."%' AND ";  
}

$outputtt1 = rtrim($outputtt1, ' OR ');
$outputtt2 = rtrim($outputtt2, ' AND ');




$query_for_result = mysql_query("SELECT * from mytable 
WHERE ".$outputtt1."
union all
SELECT * from mytable 
WHERE ".$outputtt2."
");

所以我需要找到一种方法来对包含匹配项的文章进行排序,以便首先对包含最多匹配项的文章进行排序。

你可以在这里看到我制作的脚本: http://www.genius-webdesign.com/test/querytest.php

【问题讨论】:

    标签: php mysql database search


    【解决方案1】:

    这是执行此操作的 SQL:

    select t.*
    from mytable
    order by ((title like '%keyword1%') +
              (title like '%keyword2%') +
              (title like '%keyword3%') +
              . . .
              (title like '%keywordn%')
             ) desc;
    

    MySQL 将布尔表达式视为数字,true 为 1。所以,这会计算匹配的数量。

    顺便说一句,如果您的数据有任何大小,您可能会发现全文搜索比使用like 更有效。

    编辑:

    计算关键字的数量有点困难,但你可以这样做:

    order by ((length(replace(title, 'keyword1', 'x')) -
               length(replace(title, 'keyword1', '')
              ) +
              (length(replace(title, 'keyword2', 'x')) -
               length(replace(title, 'keyword2', '')
              ) +
              . . .
              (length(replace(title, 'keywordn', 'x')) -
               length(replace(title, 'keywordn', '')
              )
             );
    

    计算关键字出现的次数比仅查找关键字出现的位置更麻烦。

    【讨论】:

    • 谢谢,我试试看
    • 这似乎不起作用。这是带有示例数据的修改后的查询: $query_for_result = mysql_query("select t.* from zt8zo_content order by ((title like '%word1%') + (title like '%word2%') + (title like '%word3%')) desc; union all SELECT * from zt8zo_content WHERE title NOT LIKE '%word1%' AND title NOT LIKE '%word2%' AND title NOT LIKE '%word3%' "); 不幸的是,这不起作用
    • @GeniusDesign 。 . .我不确定您评论中的查询与我的解决方案中的查询有什么关系。您不需要union all。答案中指定的只有一个带有order by 子句的查询。
    • 对不起,我误解了实现。将再次检查。
    • 非常感谢,我稍微修改了您的查询,现在它可以按我的意愿工作了。这是我现在使用的查询:“select * from zt8zo_content order by ((title like '%word1%') + (title like '%word2%') + (title like '%word3%')) desc”跨度>
    【解决方案2】:

    另一种使用全文搜索的方法

    SELECT *, 
      MATCH('title') AGAINST($_GET['query']) * 10 as score1, 
      MATCH('content') AGAINST($_GET['query']) * 5 AS score2
    FROM articles
    WHERE MATCH (title, content) AGAINST($_GET['query'])
    ORDER BY (score1) + (score2) DESC;
    

    如果需要的话,像这样改变你的桌子

    ALTER TABLE articles ENGINE = MYISAM;
    ALTER TABLE articles ADD FULLTEXT(title, content);
    

    【讨论】:

    • 感谢您的回答!虽然我更喜欢在这种特殊情况下使用 LIKE,因为查询会很轻松。
    • @GeniusDesign 没关系。也许有一天其他人会发现这很有用;)
    • @hex494D49 “总有一天”来了!
    猜你喜欢
    • 1970-01-01
    • 2012-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-01-06
    • 2021-06-29
    相关资源
    最近更新 更多