SQL 查询具有交集的多对多

SQL query on Many to Many with intersection

我在幕后使用 django-categories which uses django-mptt。 (这涉及我正在使用的数据库结构。)

我有一些产品:

product       
--------      
id | name     
1  | Apple    
2  | Orange   
3  | Tomato   

类别:

categories
----------
id | name       | parent | tree_id | level
1  | Type       | null   | 1       | 1
2  | Fruit      | 1      | 1       | 2
3  | Vegetable  | 1      | 1       | 2
4  | Color      | null   | 2       | 1
5  | Orange     | 4      | 2       | 2
6  | Red        | 4      | 2       | 2
7  | Green      | 4      | 2       | 2
8  | Dark green | 7      | 2       | 3
9  | Orange     | 4      | 2       | 2

这是单根树(节点也有字段orderleftright,但我认为它在这里不相关):

root/
├── Type/
│   ├── Fruit
│   ├── Vegetable
└── Color/
    ├── Red
    ├── Green
    |   └── Dark green
    └── Orange

和 M2M table:

product_categories
------------------
id | product_id | category_id
1  | 1          | 2
2  | 1          | 6
3  | 2          | 2
4  | 2          | 9
5  | 3          | 3
6  | 3          | 5

所以我将所有类别都放在一棵树中,但我可以按 tree_id 对它们进行分组。 现在我想找到 FruitsRedOrange 的产品(所以要得到 Apple an Orange)

我原以为查询会给我想要的东西:

SELECT DISTINCT 
"product"."id", "product"."name" 
FROM
"product" 
INNER JOIN "product_categories" ON ("product"."id" = "product_categories"."product_id") 
WHERE 
("product_categories"."category_id" IN ('2') 
AND "product_categories"."category_id" IN ('6', '9'))

但我没有得到任何结果。

它可以通过多次查询来实现,每棵树一次,然后寻找交集,但我相信它可以通过单次查询来实现。

试试这个:

SELECT DISTINCT 
"product"."id", "product"."name" 
FROM
"product" 
INNER JOIN "product_categories" ON ("product"."id" = "product_categories"."product_id") 
WHERE 
("product_categories"."category_id" IN ('6', '9'))
INTERSECT
SELECT DISTINCT 
"product"."id", "product"."name" 
FROM
"product" 
INNER JOIN "product_categories" ON ("product"."id" = "product_categories"."product_id") 
WHERE 
("product_categories"."category_id" IN ('2'))