简体   繁体   English

MySQL - 从分层表中获取特定类型的孩子

[英]MySQL - get children of a specific type from a hierarchical table

I have two tables, Groups and GroupHierarchy.我有两个表,Groups 和 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.类型程序的 prog1、prog2 是硕士学位的孩子。

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.给定父组 ID 和所需的组类型,查询应返回直接或间接属于父组的所需类型的所有记录。

Eg 1: Parent Group Id = 8, type = programme returns records 8 | eg 1: Parent Group Id = 8, type = program returns records 8 | 4 and 8 | 4 和 8 | 5. explanation: prog1(4) and prog2(5) are programmes under msc degree(8) 5.说明:prog1(4)和prog2(5)是msc degree(8)下的programs

Eg 2: Parent Group Id = 8, type = class returns records 4 |例2:Parent Group Id = 8, type = class 返回记录4 | 1 and 5 | 1 和 5 | 3. explanation: class1(1) and class2(3) are classes under msc degree(8) 3.说明:class1(1)和class2(3)是msc degree(8)下的classes

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.您可以使用递归 CTE 检索子弧,然后组装子节点列表,最后按类型过滤。

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 .请参阅DB Fiddle中的运行示例。

EDIT - Explanation of the Query编辑 - 查询说明

The query includes three CTEs:该查询包括三个 CTE:

  • The p CTE defines the parameters. p CTE 定义参数。
  • The r CTE selects all the children of the starting node. r CTE 选择起始节点的所有子节点。
  • The n CTE walks the tree down and selects all children of the children, and so on. n CTE 向下遍历树并选择子项的所有子项,依此类推。
  • Finally, the main query retrieves the type of each node, and filter by it.最后,主查询检索每个节点的类型,并根据它进行过滤。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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