2011-06-29 12 views
1

テーブルと一致する参加:category_idsのALL指定したリストに一致するすべての製品IDを返すSQLクエリ何ができるか初心者の質問:N-Nそれはすべてリストに

-- products -- 
    id 

-- categories -- 
    id 

-- products_categories -- 
    id 
    product_id 
    category_id 

を?

例:リスト(3、4、5)を指定すると、カテゴリID 3とカテゴリID 5のうち、少なくともLE(より多くの可能性があります)を持つすべてのproduct_idを希望しますか?

+0

あなたが必要とする関係演算子は、[すべての部品を供給するサプライヤ]として広く知られている[division](http://en.wikipedia.org/wiki/Relational_algebra#Division_.28.C3.B7.29)です。 ](http://www.dbdebunk.com/page/page/772076.htm)。それはあなたが[余分で分裂する]ように思えます(http://www.simple-talk.com/sql/t-sql-programming/divided-we-stand-the-sql-of-relational-division/)。空のdivisiorはあなたの場合はおそらく問題ではありません。 – onedaywhen

+0

BTW SQLはテーブル内のデータ行に最も適しているため、 'list'(3、4、5) 'がテーブルの3つの行としてモデル化されていると、クエリの作成と一般化が容易になります。 – onedaywhen

答えて

6

用途:

SELECT p.id 
    FROM PRODUCTS p 
    JOIN PRODUCTS_CATEGORIES pc ON pc.product_id = p.id 
    JOIN CATEGORIES c ON c.id = pc.category_id 
    WHERE c.id IN (3,4,5) 
GROUP BY p.id 
    HAVING COUNT(DISTINCT c.id) = 3 

これは俗にCelko's divisionとして知られています。

COUNT(DISTINCT c.id)は、IN句で指定された値の数と等しくなければなりません。それ以外の場合、4/3/5/etcの重複は誤検出となります。ただし、product_id, category_idのすべてのペアが一意であることが保証されている場合は、DISTINCTを省略することができます。二重否定として読み取ることができ

+0

彼はIDの – Magnus

+0

にしか関心がないので、ジョインを 'PRODUCTS'と' CATEGORIES'にスキップすることができます@Magnus:私はこの例に同意しますが、IMOは簡略化されているので、 –

0

別のオプション:

ショーその製品と一致しなかったために(3,4,5)でカテゴリが存在しないいるすべての製品。

SELECT p.id 
FROM PRODUCTS p 
WHERE NOT EXISTS 
     (SELECT * 
     FROM CATEGORIES c 
     WHERE c.id IN (3,4,5) 
      AND NOT EXISTS 
       (SELECT * 
       FROM PRODUCTS_CATEGORIES pc 
       WHERE pc.product_id = p.id 
        AND pc.category_id = c.id 
      ) 
    ) 

これは、広くDate's divisionとして知られています。