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
这是单根树(节点也有字段order
、left
、right
,但我认为它在这里不相关):
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
对它们进行分组。
现在我想找到 Fruits
和 Red
或 Orange
的产品(所以要得到 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'))
我在幕后使用 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
这是单根树(节点也有字段order
、left
、right
,但我认为它在这里不相关):
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
对它们进行分组。
现在我想找到 Fruits
和 Red
或 Orange
的产品(所以要得到 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'))