简体   繁体   English

MySQL递归查询,用于查找多对多关系的所有父级

[英]MySQL recursive query for finding all parents of a many-to-many relationship

Edit Please consider this before marking as duplicate 编辑 在标记为重复之前,请考虑这一点

The common CTE or repeated joins or similar solutions does not fully satisfy the premise of the problem. 通用CTE或重复联接或类似的解决方案不能完全满足问题的前提。 Those solutions work for one and only one root (product) while the question at hand, asks for all roots within a table or query to be traversed and flattened, without a loop. 这些解决方案针对一个且仅一个根(产品)起作用,而当前的问题则要求遍历和扁平化表或查询中的所有根,而没有循环。

Problem Definition 问题定义

I have three tables that define the characteristics of some products: 我有三个表来定义某些产品的特征:

  • specifications 规格
+----|------------------|----------|--------+
| 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 |
+----|------------------|----------|--------+
  • groups 团体
+----|-------------------|--------+
| 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 |
+----|-------------------|--------+
  • specification_groups Specification_groups
+----|----------|------------------|--------+
| 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 |
+----|----------|------------------|--------+
  • group_groups group_groups
+----|----------|--------------------|--------+
| 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 |
+----|----------|--------------------|--------+
  • product_groups product_groups
+----|--------|-------|--------+
| id |   name | group | status |
|----|--------|-------|--------|
|  1 | phone1 |     1 |      0 |
|  2 |  book1 |     8 |      0 |
+----|--------|-------|--------+

Ideally, I want to get all specification attributes for a product which the status along all tree-lines would be 0, but just to know what groups does a product is in is acceptable. 理想情况下,我想获取产品的所有规格属性,所有树状线上的状态均为0,但是只知道产品属于哪个组是可以接受的。

A result may look like this: 结果可能如下所示:

  • result 结果
+---------|-------------|--------------|-------------------|----------|--------+
| 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 |
+---------|-------------|--------------|-------------------|----------|--------+

Here's the answer if anyone else wants to do the same. 如果其他人也想这样做,这就是答案。 The trick was to use the non-recursive initial selection parameters as constants in the recursive one: 诀窍是在递归参数中使用非递归初始选择参数作为常量:

    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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM