MySQL CTE写递归解决树形查询

951 阅读1分钟

解决树形查询问题,有这样一张表,按照这个结构可以写成无限子集 image.png 在设计树形结构时,可以增加字段然后做点手脚,比如

image.png 关于这么写可以用到倒排索引详见 zhuanlan.zhihu.com/p/366875942

想要找到直属上级很简单,直接根据pid查找就行,但是想要查找所有上级,或所有属下,之前是写个函数各种自连接也是递归总之很麻烦,可以试试用MySQL的CTE(公共表表达式)来写递归

是Mysql8.0的新特性,所以如果你用的是<该版本那不能这么写

;with recursive cte() as (
    root node 递归初始条件
    union all 拼接上一次结果集
    select ..from cte ..递归调用自己
)select..from cte..执行递归

查询子节点所有父节点

;with recursive  cte(id,name,pid) as (
    select id,name,pid from club where id=5
    
    union all
    
    select  p1.id ,p1.name, p1.pid from club p1 ,cte
          where p1.id = cte.pid
)select * from cte;

结果

image.png

查询父节点的所有子节点

;with recursive  cte(id,name,pid) as (
    select id,name,pid from club where id=3
union all

select  p1.id ,p1.name, p1.pid from club p1 ,cte
                               where p1.pid = cte.id
)select * from cte;

image.png

添加Level字段

上面那篇文章提到添加字段

image.png 但是我的表中在设计时并没有level字段,所以在递归时可以添加level别名,然后查询某一节点的所有父子节点时可以用level>id |level<id 来查询

;with recursive cte as (
        select id, name, pid, name as ManagerName, 1 as Level
            from club where id = 1
            
        union all
        
        select club.id, club.name, club.pid, cte.name, cte.Level+1 as Level
             from cte cte inner join club club
             on cte.id = club.pid )
select id,name,pid,ManagerName,Level from cte where Level>3;

产品部的所有子节点

image.png