2012-01-11 8 views
2

データベースから製品を選択するためのタグシステムを実行しようとしています。私はこれを達成するための最善の方法は、多くのレコードがある場合、LIKE '%tag%'を使用することが遅くなるため、多対多の関係を使用することです。また、this質問を複数のタグに一致させるには、リクエストされている各タグの結合を行う必要があります。複数のタグを含む行を選択すると良い方法がありますか?

私は3つのテーブル:shop_products、shop_categories、shop_products_categoriesを持っています。たとえば、タグ「花」と「ロマンス」の両方を持つ商品を見つけることができるようにする必要があります。

SELECT p.sku, p.name, p.path FROM shop_products p 
    LEFT JOIN shop_products_categories pc1 ON p.sku = pc1.product_sku 
    LEFT JOIN shop_categories c1   ON pc1.category_id = c1.id 
    LEFT JOIN shop_products_categories pc2 ON p.sku = pc2.product_sku 
    LEFT JOIN shop_categories c2   ON pc2.category_id = c2.id 
WHERE c1.path = 'flowers' AND c2.path = 'romance' 

これは関連するPHPをコーディングする前に動作確認しているデモクエリです。動作します。しかしこれは本当にこれを行う最善の方法ですか?私は検索する各タグの結合を行うよりも、これを行うより良い方法がないと信じるのは難しいと思う。 アドバイスありがとうございます。 :)

答えて

3

複数の結合を行う必要はありません。あなたはあなたが一致しているユニークなタグの数であることを数2を調整する必要があります

select p.sku, p.name, p.path 
from shop_products p 
where p.sku in (
    select pc.product_sku 
    from shop_products_categories pc 
    inner join shop_categories c on pc.category_id = c.id 
    where c.path in ('flowers', 'romance') 
    group by pc.product_sku 
    having count(distinct c.path) = 2 
) 

注:すべてのタグを一致させる必要がある場合は、このようなサブクエリでIN句を使用することができます。これがユーザー入力データで、同じタグを2回入力する場合は注意してください。

+0

おかげで、。 :) – Fourjays

1
SELECT 
    p.sku, p.name, p.path 
FROM 
    shop_products p 
    INNER JOIN 
    (
     SELECT A.sku FROM 
     (
      SELECT product_sku sku FROM shop_products_categories 
      WHERE category_id=(SELECT id FROM shop_categories WHERE path='flowers') 
     ) A 
     INNER JOIN 
     (
      SELECT product_sku sku FROM shop_products_categories 
      WHERE category_id=(SELECT id FROM shop_categories WHERE path='romance') 
     ) B 
     USING (sku) 
    ) flowers_and romance 
    USING (sku) 
; 

あなたはこれらのインデックスを持っていることを確認してください:素晴らしい仕事

ALTER TABLE shop_categories ADD INDEX (path,id); 
ALTER TABLE shop_categories ADD UNIQUE INDEX (path); 
ALTER TABLE shop_products_categories ADD INDEX (product_sku,category_id); 
関連する問題