PostgreSQL-With子句实现递归

PostgreSQL-With子句实现递归

上手:

自顶向下
with recursive tree AS (
    select dep.id,dep.name,dep.parent_id from department dep where dep.id = 1

    union all 

    select dep.id,dep.name,dep.parent_id from department dep inner join tree on dep.parent_id = tree.id
) select * from tree;

 

sql  实现 菜单树展示:

WITH RECURSIVE tree AS (
SELECT
dep.ID,
dep.NAME,
dep.type,
dep.code,
dep.route,
dep.market_app_id,
dep.icon,
dep.parent_id
FROM
uaa_res_ui dep
WHERE
dep.id = 171989007847143424 UNION ALL
SELECT
dep.ID,
dep.NAME,
dep.type,
dep.code,
dep.route,
dep.market_app_id,
dep.icon,
dep.parent_id
FROM
uaa_res_ui dep
INNER JOIN tree ON dep.parent_id = tree.ID
) SELECT
*
FROM
tree;

该语句是从子部门(id = 7)向上查询,即查询该部门的父部门。同样的我们也可以修改第二行后数值 ”7“ 来查看不同的结果。如下:

-- 自下向上
with recursive tree as (
    select dep.id,dep.name,dep.parent_id from department dep where dep.id =7

    union all 

    select dep.id,dep.name,dep.parent_id from department dep inner join tree on tree.parent_id = dep.id
) select * from tree;

-- 查询的结果
-- id   name    parent_id
-- 7    二级部门3   2
-- 2    一级部门1   1
-- 1    *部门    0

注意:

语法

with recursive 名字 as (
    A.初始语句(非递归部分)

    union all 

    B.递归部分语句

) [SELECT | INSERT | UPDATE | DELETE]

可以到 WITH RECURSIVE 与普通的 WITH 相比,最大的不同就是 as () 中的 的内容。内容被 union all 一分为二,前半部分 A 为非递归语句,后半部分 B 为要进行的递归语句。

执行步骤如下

  1. 执行 A 部分。(如果使用的是union而非union all,则需对结果去重)其结果作为 B 中对result的引用,同时将这部分结果放入临时的working table中
  2. 重复执行如下步骤,直到working table为空:用working table的内容替换递归的自引用,执行 B ,(如果使用union而非union all,去除重复数据),并用该结果(如果使用union而非union all,则是去重后的结果)替换working table

注意项

  1. 初始语句 A 中的列与递归部分语句 B 的列必须要一一对应
  2. 初始语句 A 、递归部门语句 B 查询的时候不要使用 * 号来代替列
  3. 一定要有结束条件,否则会进入死循环