2010-12-03 8 views
0

私はここに少し難解です。私はレシピアプリケーションを焼いていて、 "マヨネーズ"、 "ベーコン"、 "チーズ"のクエリがあるとしましょう。MySQLはUNIONを取得し、交差点で注文しますか?

"マヨネーズ"、 "ベーコン"、 "チーズ"が含まれているレシピはすべて、 "マヨネーズ"、 "ベーコン"、 "チーズ"、次に "マヨネーズ" ANDなど「ベーコン」、

は、これまでのところ私は少し好きcloogey何か持っている:

SELECT * FROM recipes 
    WHERE LOWER(ingredients) LIKE '%mayonnaise%' 
    OR LOWER(ingredients) LIKE '%bacon%' 

をしかし、それは私が何をしたいのちょうど半分です。フィニッシュラインをどのように乗り越えるのですか?

ありがとうございます!

+0

これは分かっていますが、データベース設計は理想的ではありません。正規化すれば、パフォーマンスが向上し、これらのタイプのクエリーを簡単に作成できるようになります。 –

答えて

1

あなたは成分が含まれているか否かによって、食材や秩序の存在を優先試みることができる:

SELECT * FROM recipes 
WHERE LOWER(ingredients) LIKE '%mayonnaise%' 
OR LOWER(ingredients) LIKE '%bacon%' 
OR LOWER(ingredients) LIKE '%cheese%' 
ORDER BY LOWER(ingredients) LIKE '%mayonnaise%' DESC, 
     LOWER(ingredients) LIKE '%bacon%' DESC, 
     LOWER(ingredients) LIKE '%cheese%' DESC 
+0

これはうまくいった!ありがとうございました! – Rio

0

レシピが主キーを持っている場合、私は知らないが、私はそれがないと仮定します。単語ごとに1ポイントをあげましょう。

SELECT r.* FROM recipes 
LEFT JOIN recipes m ON r.id = m.id AND LOWER(m.ingredients) LIKE '%mayonnaise%' 
LEFT JOIN recipes b ON r.id = b.id AND LOWER(b.ingredients) LIKE '%bacon%' 
LEFT JOIN recipes c ON r.id = c.id AND LOWER(c.ingredients) LIKE '%cheese%' 
ORDER BY 
(CASE WHEN m.id IS NULL THEN 0 ELSE 1 END)+ 
(CASE WHEN b.id IS NULL THEN 0 ELSE 1 END)+ 
(CASE WHEN c.id IS NULL THEN 0 ELSE 1 END) DESC 
+0

これはすばらしい解決策でしたが、12,000レコードを実行するのに約8秒かかりました。私はこれがデータ構造を反映していることを認識していますが、それにもかかわらずありがとうございます! – Rio

+0

@Rio合意しました。確かに効率的ではありません。あなたの目的に合った何かを見つけられたらうれしいです! –

0

可能であれば(新しいものを作成しているように)、テーブルレイアウトを再考する必要があります。おそらくカンマで区切られたものか、何かがあると思われます。これは実際にはうまくスケールされず、複雑で低速なような単純なクエリでさえも(実際の検索語の前にあるこれらのすべてのワイルドカードを使用すると、インデックスの使用は効果的に無効になります)。

おそらく、RECIPESテーブルに対するn:mカーディナリティの関係で、別のINGREDIENTSテーブルを使用することをお勧めします。擬似-SQLで

CREATE TABLE RECIPES (id int not null, [...more columns...]) PRIMARY KEY id; 
CREATE TABLE INGREDIENTS (id int not null, name varchar(30), [...more columns...]) PRIMARY KEY id; 
CREATE TABLE RECIPE_INGREDIENTS (recp_id int not null, ingred_id not null); 

あなたがレシピや食材を参加できそうすれば:

SELECT RECIPES.id AS recipe, COUNT(INGREDIENTS.id) AS matching_ingredients 
    FROM RECIPES r JOIN RECIPE_INGREDIENTS ri ON r.ID=ri.recp_id 
        JOIN INGREDIENTS i ON ri.ingred_id = i.id 
    WHERE INGREDIENTS.name in ('mayonnaise', 'bacon', 'cheese') 
GROUP BY COUNT(INGREDIENTS.id) 

レシピ番号のテーブルと一致する成分の数をリードします。これはインデックスからも恩恵を受けるでしょう。

私は今のところ手元にMySQLサーバーを持っていないので、上記は私の頭の上から書かれています。たぶん私は少し間違って構文を持っています。さらに、Foreign Key情報を追加したいと思うかもしれませんが、それは実行するために厳密には必要ではありません。

これについては、MySQLマニュアルのCREATE TABLEの構文を参照してください。

+0

パフォーマンスに関しては間違いありません。私は、成分を抽出しようとすることについてもっと深く考えなければならないでしょう。 – Rio

関連する問題