0

列id(int)、name(varchar)、およびinfo(text)を持つテーブルInnoDBがあります。特定の用語を使用してテーブルの name 列と info 列を検索し、各レコードで結合された 2 つの列の「ヒット」数に従って、一致するレコードを上位から下位にランク付けする必要があります。

私はトロールしましたが、これまで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」は検索語です)

これは 1 行 1 列の 'count' を返し、値は 3 です...これは、mo のテーブルに 3 つのレコードがあるためだと思います。

私もこれを見つけて試しました:

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」が含まれていることがわかっている場合、これは明確な順序ではなく、1 つを除くすべてのレコードを返しました。

4

2 に答える 2

3

Thw following will rank rows by the number of columns (0 through 2) matching your term:

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

This makes use of the fact that a boolean value, like the result of LIKE, is represented by an integer in MySQL, 0 for false and 1 for true. So you can simply add them, without any case distinction.

If you want to find multiple counts, you'll probably have to write a stored procedure that loops over your string, as there is no basic string function that counts matches. Unless the amount of data is really large, you might be better of by computing these counts in the application instead of on the database server.

Your first code snippet simply returns the number of rows that contain an a in either column. This is because COUNT is an aggregating column, which (in the absence of a GROUP BY) will combine all your rows into a single row. The second snippet will only choose rows which have a in both columns, so the ordering number will always be 2, causing the apparent lack of ordering.

于 2012-11-01T00:46:20.700 に答える
1

やった!インスピレーションを与えてくれた@MvGに感謝します。私はMySQLよりもPHPの方がはるかに優れているので、次のようにして問題を解決しました。(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 に答える