2009-08-22 17 views
5

私は単純な使用された送信フィールドを使用してMySQLでレコードを取得しようとしています。より正確には、ユーザーは名前(ファーストネームまたはラストネームまたはフルネーム)を入力し、サーバーは一致する行を返す必要があります。今のところうまく動作しますが、ユーザーはフルネームを提出するときには、(明らかに)動作しませんMySQLのHAVING句とWHERE句の間に 'OR'を使用していますか?

SELECT * FROM people 
WHERE 
    firstname LIKE '%user_submitted_data%' OR 
    lastname LIKE '%user_submitted_data%' 

:私はこれまで何をやっている

のようなものです。 「WHEREタイプ条件」と「HAVINGタイプ条件」の間にORを追加する方法はありますか?私のような何かを行うことができ、この方法:

SELECT [some fields], CONCAT(firstname, ' ', 'lastname') as fullname 
FROM people 
WHERE 
    firstname LIKE '%user_submitted_data%' OR 
    lastname LIKE '%user_submitted_data%' OR 
    HAVING fullname LIKE '%user_submitted_data%' 

は、私はちょうど元の文字列を分割する可能性が知っていますが、このような「デ・Gaule」とそのようなものとして、スペースを含む名前に対処する必要があるため、それはいくつかのマイナスの影響を与えています。

答えて

4

サブクエリを実行します。ユーザーは、第1の入力に入ったときに、今

SELECT * FROM people 
WHERE 
    firstname LIKE '%user_submitted_data%' OR 
    lastname LIKE '%user_submitted_data%' 

John 
Smith 
John Smith 

あなたの最初のサンプルクエリは、次のとおりです。

SELECT [some fields] 
FROM 
    SELECT firstname, lastname, CONCAT(firstname, ' ', lastname) as fullname 
    FROM people) AS tmp 
WHERE firstname LIKE '%user_submitted_data%' 
OR lastname LIKE '%user_submitted_data%' 
OR fullname LIKE '%user_submitted_data%' 
+0

ありがとう、それを修正します。 – Jimmy

1

はのは、いくつかの可能な入力を考えてみましょうこのクエリは、最初の名前に 'John'が含まれているすべての人物を選択します。また、姓が 'John'(たとえば、データベース内のすべてのJohnsons)を含むすべての人物を選択します。同様に、2番目の入力は、最初の名前に 'Smith'が含まれているすべての人物を選択します。姓が 'Smith'(SmithsonsとSmithersなど)を含むすべての人物も選択します。ここまでは順調ですね;大文字と小文字を区別する問題があるため完璧ではありません(ここでは大文字と小文字を区別しませんが、無視しないでください)が、問題ありません。

3番目の入力は、最初の名前に「John Smith」が含まれる人のみを選択します。姓が 'John Smith'を含む人物も選択します。しかし、ジョン・スミスと呼ばれる人々は、ファースト・ネームにジョンだけ、姓にスミスだけを持つことになります。これは、あなたが念頭に置いていたものである可能性は低いです。

テーブルに 'fullname'という列があるかどうかは不明です。そうした場合は、最初の名前と最後の名前を別々に照合するのではなく、その列と照合するだけで済みます。そうでない場合は、そのような列を作成してそれに対してクエリを実行することができます。

SELECT * 
    FROM (SELECT firstname || ' ' || lastname AS fullname, ... FROM people) AS t 
WHERE t.fullname LIKE '%user_submitted_data%' 

これは合理的にうまくいきます。

「Charles De Gaulle」(または「Charles de Gaulle」)や「Michael van den Berg」などの名前が心配されている場合、「Charles Gaulle」または「Charles De Gaulle」 Michael Berg '、マイケル・バンデンバーグはもちろんのこと、おそらく、ユーザー入力の空白文字を '%'記号で置き換える必要があります。それでも、ユーザーが指定した順序で単語が表示されなければならないという問題に直面しています。これは重要ではないかもしれませんが、意識せずに重要であると判断する必要があります。たとえば、入力が 'Adam John Smith'の場合、クエリは 'John Adam Smith'をキャッチしません。入力が「Smith、John」の場合、誰も(おそらく)誰も拾わないでしょう。

これを管理したい場合は、おそらくユーザの入力をトークン化し、別の単語を検索する必要があります。誰かが単語のサブストリングを尋ねることに注意してください(例えば、誰かが名前の単語として 'de'を尋ねます)。 - 現時点の質問のどれも、ユーザーの入力単語が値の全単語にマッチすることはありませんJohnson)、そしてSQL標準のLIKE演算子でそうすることは十分に不可能です。

+0

深いawnserをありがとう。何らかの理由で、MySQLが私のシステム(OSX)で大文字と小文字を区別しないように思われるので、これまでのところうまくいっています。単語順になる限り、LIKE演算子は文脈に非常によく合います。ユーザーがJohn Adam Smithを検索しているときに、Johh Smithが出てくる必要はありません。検索サンプルは非常に限られています。 – Jimmy

0

あなたはサブクエリでその列を定義する場合は、WHERE句に計算列を参照することができます。

SELECT p.* 
FROM (
    SELECT [some fields], CONCAT(firstname, ' ', 'lastname') as fullname 
    FROM people 
) p 
WHERE 
    p.firstname LIKE '%user_submitted_data%' OR 
    p.lastname LIKE '%user_submitted_data%' OR 
    p.fullname LIKE '%user_submitted_data%'; 

をしかし、正直なところ、あなたがやっている検索の種類のために、ワイルドカードを持つLIKEはひどいソリューションです。 。

CREATE FULLTEXT INDEX people_names ON people(firstname, lastname); 

SELECT * 
FROM people 
WHERE MATCH(firstname, lastname) AGAINST(?); 

PS:あなたはFULLTEXTインデックスを使用して考えなければならないFULLTEXTインデックスは、MyISAMストレージエンジンでのみ動作します。もう1つの解決策は、フルテキストインデックス作成にSphinx Searchを使用することです。

0

サブクエリはうまく機能しますが、インデックスを使用していないため影響があります。

テーブルに計算カラム(firstname || ' ' || lastname)を追加するとどうなりますか?確かにはるかに速いでしょう。

あなたは私が

WHERE firstname || ' ' || lastname LIKE '%user_submitted_data%' 

のように照会すると、まだ2 OR sおよび1つのサブクエリよりも速く動作するはずだと思うことを行うことができない場合。

+0

MySQLでインデックス付きの計算カラムを作成する方法がないと思っています。それが可能なら、それについて聞いてみたいと思います。 – Jimmy

+0

あなたは正しいかもしれませんが、私は計算された列を全く使用する方法がないと思います! – Sklivvz

+0

一方、MySQLはインデックス付きの計算カラムをサポートしています。しかし、パターンがプレースホルダ( '%')で始まる場合、LIKE条件はインデックスを使用できません。 –

7

すべての条件をHAVING句に入力するだけです。

SELECT [some fields], CONCAT(firstname, ' ', 'lastname') as fullname 
FROM people 
HAVING firstname LIKE '%user_submitted_data%' 
OR  lastname LIKE '%user_submitted_data%' 
OR  fullname LIKE '%user_submitted_data%

WHERE句が早期に行を捨てることができますが、後、あなたが計算列に条件を評価し、それがHAVINGまで待たなければならないまであなたがそれらを捨てることができないので、それはあなたが使用することは何も買ってないWHERE

+0

私のために働いて、サブクエリを使用するよりもはるかにエレガントなソリューションのようです。ありがとうございました! –