0

我有一个表 InnoDB,其中包含 id(int)、name(varchar) 和 info(text) 列。我需要使用给定的术语搜索表的名称和信息列,并根据每条记录组合的两列中的“命中”数从高到低排列匹配记录。

我已经搜索过了,但我以前从来没有用 MySQL 做过这样的事情,发现这一切有点令人困惑......大小写和匹配等等等。

谁能提供一些快速帮助?

这是据我所知:

SELECT count(*) as count
FROM artistmanager_artists WHERE
case when 'name' LIKE '%a%' then 1 else 0 end
+ case when 'info' LIKE '%a%' then 1 else 0 end
ORDER BY count ASC

(“a”是搜索词)

它返回一行和一列,'count',值为三......我猜这是因为我在 mo 的表中有三条记录?

我也发现并尝试了这个:

SELECT *
FROM `artistmanager_artists`
WHERE `name` LIKE '%a%'
AND (
   `info` LIKE '%a%'
)
ORDER BY (
  (
      CASE WHEN `name` LIKE '%a%'
      THEN 1
      ELSE 0
      END
  ) + (
     CASE WHEN `info` LIKE '%a%'
     THEN 1
     ELSE 0
     END
  )
) DESC

这返回了除了一条记录之外的所有记录,没有明显的顺序,当我知道它没有返回的记录包含很多“a”时!

4

2 回答 2

3

Thw 以下将按与您的术语匹配的列数(0 到 2)对行进行排名:

SELECT (name LIKE '%a%') + (info LIKE '%a%') AS rnk
FROM artistmanager_artists
ORDER BY rnk DESC

这利用了布尔值(如 的结果)LIKE在 MySQL 中由整数表示的事实,0 表示假,1 表示真。所以你可以简单地添加它们,不区分大小写。

如果您想查找多个计数,您可能必须编写一个循环遍历您的字符串的存储过程,因为没有计算匹配项的基本字符串函数。除非数据量真的很大,否则最好在应用程序中而不是在数据库服务器上计算这些计数。

您的第一个代码段仅返回任一列中包含 的行数a。这是因为COUNT它是一个聚合列,它(在没有 a 的情况下GROUP BY)会将所有行合并为一行。第二个片段将只选择a列中都有的行,因此排序号将始终为2,导致明显缺乏排序。

于 2012-11-01T00:46:20.700 回答
1

我已经做了!感谢@MvG 的启发。因为我的 PHP 比我的 MySQL 好得多,所以我通过执行以下操作解决了这个问题:(我正在使用 Codeignite btw)

public function get_artists_search($search_term)
{
    $artists = array();
    $query = $this->db->query('SELECT id, name, info, (name LIKE "%' . $search_term . '%") + (info LIKE "%' . $search_term . '%") AS rnk FROM artistmanager_artists ORDER BY rnk DESC');
    foreach ($query->result() as $row)
    {
        // returned rows have at least one occurence in at least one of the two columns, so values are 1 or 2
        $artists[$row->id]['name'] = $row->name;
        $artists[$row->id]['info'] = $row->info;
        $artists[$row->id]['score'] = 0;
    }
    // now foreach returned row find occurence values.
    foreach($artists AS $key=>$artist)
    {
        $score_name = substr_count(strtoupper($artist['name']), strtoupper($search_term));
        $score_info = substr_count(strtoupper($artist['info']), strtoupper($search_term));
        $artists[$key]['score'] = $score_name+$score_info;
        unset($artists[$key]['name']);
        unset($artists[$key]['info']);
    }
    arsort($artists);
}

它返回一个数组,其中记录的 id 作为键和排名值,从高到低排序。我测试了它并且它有效,所以我很高兴。

感谢大家对横向思维的帮助!

于 2012-11-01T09:27:02.210 回答