简体   繁体   中英

MySQL - get children of a specific type from a hierarchical table

I have two tables, Groups and GroupHierarchy. They have the following data.

GROUP:

id   |  Name      | type

8    |  M.Sc      | degree  
4    |  prog1     | programme   
5    |  prog2     | programme   
1    |  class1    | class   
3    |  class2    | class

GROUP HIERARCHY:

parentGroupId | childGroupId

8             | 4

8             | 5

4             | 1

5             | 3

prog1, prog2 of type programme are children of degree M.Sc.

i want to perform the following query. Given the parent group id and required group type, the query should return all records of the required type that are children of the parent directly or indirectly.

Eg 1: Parent Group Id = 8, type = programme returns records 8 | 4 and 8 | 5. explanation: prog1(4) and prog2(5) are programmes under msc degree(8)

Eg 2: Parent Group Id = 8, type = class returns records 4 | 1 and 5 | 3. explanation: class1(1) and class2(3) are classes under msc degree(8)

how to frame a query that returns the above results?

You can use a recursive CTE to retrieve the child arcs, then assemble a list of the child nodes, and finally filter by type.

For example:

with recursive
p as (select 8 as id, 'programme' as type),
r as (select h.* from h cross join p where h.parentGroupId = p.id),
n as (
  select * from r
 union all
  select h.*
  from n
  join h on h.parentGroupId = n.childGroupId
)
select g.*
from (
  select childGroupId as id from n
  union all select distinct parentGroupId from r
) a
join g on g.id = a.id
join p on p.type = g.type;

Result:

 id  name   type      
 --- ------ --------- 
 4   prog1  programme 
 5   prog2  programme 

And by changing the parameter in the second line:

with recursive
p as (select 8 as id, 'class' as type),
r as (select h.* from h cross join p where h.parentGroupId = p.id),
n as (
  select * from r
 union all
  select h.*
  from n
  join h on h.parentGroupId = n.childGroupId
)
select g.*
from (
  select childGroupId as id from n
  union all select distinct parentGroupId from r
) a
join g on g.id = a.id
join p on p.type = g.type

Result:

 id  name    type  
 --- ------- ----- 
 1   class1  class 
 3   class2  class 

See running example at DB Fiddle .

EDIT - Explanation of the Query

The query includes three CTEs:

  • The p CTE defines the parameters.
  • The r CTE selects all the children of the starting node.
  • The n CTE walks the tree down and selects all children of the children, and so on.
  • Finally, the main query retrieves the type of each node, and filter by it.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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