[英]MySQL recursive query for finding all parents of a many-to-many relationship
編輯 在標記為重復之前,請考慮這一點
通用CTE或重復聯接或類似的解決方案不能完全滿足問題的前提。 這些解決方案僅針對一個且僅一個根(產品)起作用,而當前的問題則要求遍歷和扁平化表或查詢中的所有根,而沒有循環。
問題定義
我有三個表來定義某些產品的特征:
+----|------------------|----------|--------+
| id | name | type | status |
|----|------------------|----------|--------|
| 1 | height | float | 0 |
| 2 | width | float | 0 |
| 3 | length | float | 0 |
| 4 | weight | float | 0 |
| 5 | colour | int | 0 |
| 6 | material | int | 0 |
| 7 | manufacturer | int | 0 |
| 8 | durability | float | 0 |
| 9 | battery_type | int | 0 |
| 10 | battery_capacity | float | 0 |
| 11 | connectivity | set<int> | 0 |
| 12 | page | int | 0 |
| 13 | name | string | 0 |
| 14 | description | string | 0 |
+----|------------------|----------|--------+
+----|-------------------|--------+
| id | name | status |
|----|-------------------|--------|
| 1 | cellphone | 0 |
| 2 | notebook | 0 |
| 3 | portable | 0 |
| 4 | workstation | 0 |
| 5 | pc | 0 |
| 6 | computer | 0 |
| 7 | electronic_device | 0 |
| 8 | book | 0 |
| 9 | sizeable | 0 |
| 10 | volumable | 0 |
| 11 | general | 0 |
+----|-------------------|--------+
+----|----------|------------------|--------+
| id | group_id | specification_id | status |
|----|----------|------------------|--------|
| 1 | 11 | 13 | 0 |
| 2 | 11 | 14 | 0 |
| 3 | 11 | 5 | 0 |
| 4 | 10 | 1 | 0 |
| 5 | 9 | 2 | 0 |
| 6 | 9 | 3 | 0 |
| 7 | 8 | 12 | 0 |
| 8 | 3 | 6 | 0 |
| 9 | 3 | 9 | 0 |
| 10 | 3 | 10 | 0 |
| 11 | 7 | 7 | 0 |
| 12 | 7 | 11 | 0 |
+----|----------|------------------|--------+
+----|----------|--------------------|--------+
| id | group_id | group_reference_id | status |
|----|----------|--------------------|--------|
| 1 | 3 | 1 | 0 |
| 2 | 3 | 2 | 0 |
| 3 | 3 | 8 | 0 |
| 4 | 6 | 4 | 0 |
| 5 | 6 | 5 | 0 |
| 6 | 7 | 1 | 0 |
| 7 | 7 | 2 | 0 |
| 8 | 7 | 4 | 0 |
| 9 | 7 | 5 | 0 |
| 10 | 9 | 7 | 0 |
| 11 | 9 | 8 | 0 |
| 12 | 10 | 7 | 0 |
| 12 | 11 | 7 | 0 |
| 12 | 11 | 8 | 0 |
+----|----------|--------------------|--------+
+----|--------|-------|--------+
| id | name | group | status |
|----|--------|-------|--------|
| 1 | phone1 | 1 | 0 |
| 2 | book1 | 8 | 0 |
+----|--------|-------|--------+
理想情況下,我想獲取產品的所有規格屬性,所有樹狀線上的狀態均為0,但是只知道產品屬於哪個組是可以接受的。
結果可能如下所示:
+---------|-------------|--------------|-------------------|----------|--------+
| row_num | product_id | product_name | product_group | group_id | status |
|---------|-------------|--------------|-------------------|----------|--------|
| 1 | 1 | phone1 | cellphone | 1 | 0 |
| 2 | 1 | phone1 | portable | 3 | 0 |
| 3 | 1 | phone1 | electronic_device | 7 | 0 |
| 4 | 1 | phone1 | sizable | 9 | 0 |
| 5 | 1 | phone1 | volumable | 10 | 0 |
| 6 | 1 | phone1 | general | 11 | 0 |
| 7 | 2 | book1 | book | 8 | 0 |
| 8 | 2 | book1 | portable | 3 | 0 |
| 9 | 2 | book1 | sizable | 9 | 0 |
| 10 | 2 | book1 | general | 11 | 0 |
+---------|-------------|--------------|-------------------|----------|--------+
如果其他人也想這樣做,這就是答案。 訣竅是在遞歸參數中使用非遞歸初始選擇參數作為常量:
with recursive
q as (
select * from product_groups as pg where ur.`status` = 0
)
, ancestors as (
(
select q.id as `product_id`, q.product_name as `product_name`, gg.group_id as `group_id`, gg.group_reference_id as `group_reference_id`
from group_groups as gg
join q on gg.group_id = q.group_id
where gg.`status` = 0
)
union
(
select q.id as `product_id`, q.product_name as `product_name`, null as `group_id`, q.group_id as `group_reference_id`
from q
)
union
(
select a.id as `product_id`, a.product_name as `product_name`, gg.group_id as `group_id`, gg.group_reference_id as `group_reference_id`
from group_groups as gg, ancestors as a
where gg.group_id = a.group_reference_id and gg.`status` = 0
)
)
select distinct
t.id as `product_id`, t.`group_id` as `group_id`, t.specification_id as `specification_id`, t.product_name as `product_name`, t.group_name as `group_name`, s.name as `specification_name`
from
(
select a.product_id, a.group_reference_id as `group_id`, sg.specification_id as `specification_id`, a.product_name, g.name as `group_name`
from ancestors as a
right join specification_groups as sg on a.group_reference_id = sg.group_id
where a.product_id is not null and sg.`status` = 0
) as t
join specifications as s on t.specification_id = s.id
order by product_id asc, group_id, asc, specification_id asc
;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.