0

这是非常简单的问题。

我想查找文本字段包含文本以填充表单中的自动完成字段的记录。挑战在于我想将结果限制为前 20 条记录,但优先考虑字段开头的匹配项。

我现在如何执行此操作是执行field LIKE "%term"10 的查询,然后在field LIKE "%term%"10 的位置追加记录。它需要两次搜索。

是否可以仅通过表的一个查询来做到这一点?按场上比赛的位置排序?

4

3 回答 3

4

是的,可以按搜索字符串的第一次出现进行排序。(我假设你想写字段 LIKE "term%"。)

SELECT *, LOCATE('term', field) as rev_score FROM table WHERE field LIKE "%term%" ORDER BY rev_score DESC LIMIT 20;

然而,这个查询很可能比字段“term%”慢得多(假设您在字段上有一个索引)。

  • 在您的情况下,字段 LIKE "term%" 可以通过字段上的索引来实现,从而导致范围查询,但仍然很快。
  • 如果您不使用订单,字段 LIKE "%term%" LIMIT 10 仍然可以更快(呃)。根据搜索词和数据分布,统计速度比我编写的解决方案快 2 倍。原因是因为 MySQL 将开始扫描表以搜索“term”(此处不能使用索引)。当它找到 10 个元素时,它将停止。这可以在表的开头。
  • 我写的内容将导致 MySQL 对整个表进行全面扫描,并检查每一行是否有“术语”,而不是对计算值进行文件排序。可能是单个表查找中可能发生的最糟糕的事情。

我会说尝试两个版本并选择更快的版本。或者,如果您的数据集很大,您可以查看 MySQL 的全文搜索功能(MYISAM 拥有它,InnoDB 自 MySQL 5.6 起也支持它)。

于 2013-07-29T14:58:15.723 回答
1

我会做:

SELECT * FROM table WHERE field LIKE '%term%' order by IF(field REGEXP '^term.*',0,1),field LIMIT 20;
于 2013-07-29T15:10:23.473 回答
1

聪明的!我不知道这是否可能,但我知道你可以如何做得更好:

<?php

$q = 'term';
$limit = 20;

$first = mysql_query("SELECT * FROM some_table WHERE name LIKE '%$q' ORDER BY name LIMIT $limit");
$first_len = !$sql?0:mysql_num_rows($first);
$limit -= $first_len;
$second = mysql_query("SELECT * FROM some_table WHERE name LIKE '%$q%' LIMIT $limit");
$second_len = !$sql?0:mysql_num_rows($second);

if (!$first_len && !$second_len) {
    exit('No results found.');
}

function handleSearchResultRow($row) {
    echo $row['name'].'<br/>';
}

if ($first_len)
    while ($row = mysql_fetch_array($first))
        handleSearchResultRow($row);

if ($second_len)
    while ($row = mysql_fetch_array($second))
        handleSearchResultRow($row);

?>

多田!您将得到相同的结果,但代码略多!这将确保始终有多达 20 个结果,结果从学期开始!

如果您真的想要“按字段中匹配的位置排序”,那么我认为您必须创建一个包含所有结果的数组并使用 php strpos() 对其进行排序。但是 SQL 真的很强大,而且可能也有能力做到这一点。请发布另一个答案并告诉我您是否知道如何做到这一点。:)

于 2013-07-29T14:56:53.160 回答