web-dev-qa-db-ja.com

MySQLでキーワード検索を実装する方法は?

私はSQLプログラミングが初めてです。

フィールドがidpositioncategorylocationsalary rangedescriptionrefno

フロントエンドからキーワード検索を実装したい。キーワードは、上記の表の任意のフィールドに存在できます。

これは私が試したクエリですが、非常に多くの重複行で構成されています:

SELECT
    a.*,
    b.catname
FROM
    job a,
    category b
WHERE
    a.catid = b.catid AND
    a.jobsalrange = '15001-20000' AND
    a.jobloc = 'Berkshire' AND
    a.jobpos LIKE '%sales%' OR
    a.jobloc LIKE '%sales%' OR
    a.jobsal LIKE '%sales%' OR
    a.jobref LIKE '%sales%' OR
    a.jobemail LIKE '%sales%' OR
    a.jobsalrange LIKE '%sales%' OR
    b.catname LIKE '%sales%'
34
santanu

VARCHARフィールドの単一のキーワードには、 LIKE を使用できます。

SELECT id, category, location
FROM table
WHERE
(
    category LIKE '%keyword%'
    OR location LIKE '%keyword%'
)

説明については、通常、フルテキストインデックスを追加して フルテキスト検索 (MyISAMのみ)を実行する方が適切です。

SELECT id, description
FROM table
WHERE MATCH (description) AGAINST('keyword1 keyword2')
53
Greg
SELECT 
    *
FROM 
    yourtable
WHERE 
    id LIKE '%keyword%' 
    OR position LIKE '%keyword%'
    OR category LIKE '%keyword%'
    OR location LIKE '%keyword%'
    OR description LIKE '%keyword%'
    OR refno LIKE '%keyword%';
7
Jon Bright

理想的には、フィールドを含むキーワードテーブルを用意します。

Keyword
Id
Count (possibly)

キーワードのインデックス付き。他のテーブルで挿入/更新/削除トリガーを作成して、行が変更されたときにすべてのキーワードが抽出され、このテーブルに入れられる(または置き換えられる)ようにします。

また、キーワードとしてカウントされない単語のテーブルも必要になります(if、and、so、しかし、...)。

この方法で、キーワードを探したいクエリに対して最高の速度が得られ、「contains Java and RCA1802」などのより複雑なクエリを(比較的簡単に)実装できます。

"LIKE"クエリは機能しますが、同様にスケールしません。

6
paxdiablo

スレッドには別のより簡単なオプションがあります: Match Against ..11.9.2。Boolean Full-Text Searches

これは、誰かがよりコンパクトなオプションを必要とする場合のためです。これには、テーブルにインデックスFULLTEXTを作成する必要がありますが、これは簡単に実行できます。

インデックスの作成方法に関する情報(MySQL): MySQL FULLTEXT Indexing and Searching

FULLTEXTインデックスには、複数の列を一覧表示できます。結果は、searchという名前のインデックスを持つSQLステートメントになります。

SELECT *,MATCH (`column`) AGAINST('+keyword1* +keyword2* +keyword3*') as relevance  FROM `documents`USE INDEX(search) WHERE MATCH (`column`) AGAINST('+keyword1* +keyword2* +keyword3*' IN BOOLEAN MODE) ORDER BY relevance;

複数の列を試してみましたが、運はありませんでした。インデックスで複数の列を使用できますが、Match/Againstステートメントで使用するには各列にインデックスが必要です。

基準に応じて、いずれかのオプションを使用できます。

5
raphie

個人的には、IDフィールドやその他の数値フィールドでLIKE文字列比較を使用しません。 ID#の検索には意味がありません "216「16を返す216、 21651、3216087、5321668 ...など。同様に給料で。

また、準備済みステートメントを使用してSQLインジェクションを防止する場合は、次のようなクエリ文字列を使用します。

SELECT * FROM job WHERE `position` LIKE CONCAT('%', ? ,'%') OR ...
5
Calvin

私が普段好む方法を説明します:

まず、この方法では、計算速度を上げるためにメモリを犠牲にすることを考慮する必要があります。次に、テーブル構造を編集する権限が必要です。

1)テーブルのすべてのデータを保存するフィールド(通常は「ダイジェスト」と呼びます)を追加します。

フィールドは次のようになります。

"n-n1-n2-n3-n4-n5-n6-n7-n8-n9"などここで、nは単一の単語です

これを実現するには、正規表現を使用して、「」を「-」に置き換えます。このフィールドは、すべてのテーブルデータが1つの文字列で「消化」された結果です。

2)ダイジェストフィールドでLIKEステートメント%keyword%を使用します。

SELECT * FROM table WHERE digest LIKE %keyword%

少しループしたqUeryを構築して、次のように複数のキーワードを同時に検索することもできます。

SELECT * FROM table WHERE 
 digest LIKE %keyword1% AND 
 digest LIKE %keyword2% AND 
 digest LIKE %keyword3% ... 
4

私はこれが少し遅いことを知っていますが、私がアプリケーションにしたことはこれです。これが誰かを助けることを願っています。しかし、それは私にとってはうまくいきます:

SELECT * FROM `landmarks` WHERE `landmark_name` OR `landmark_description` OR `landmark_address` LIKE '%keyword'
OR `landmark_name` OR `landmark_description` OR `landmark_address` LIKE 'keyword%' 
OR `landmark_name` OR `landmark_description` OR `landmark_address` LIKE '%keyword%'
1
AndroidNewbie