新手问题:N-N联接匹配所有列表

时间:2011-06-29 16:16:16

标签: sql postgresql aggregate-functions

表格:

-- products --
   id

-- categories --
   id

-- products_categories --
   id
   product_id
   category_id

什么是SQL查询,它返回与给定的category_ids列表匹配的所有产品ID?

示例:给定列表(3,4,5)我希望所有具有至少(可能更多)类别ID 3和类别ID 4以及类别ID 5的product_ids?

2 个答案:

答案 0 :(得分: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 /等将是误报。但是,如果保证所有product_id, category_id对都是唯一的,则可以省略DISTINCT

答案 1 :(得分: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