本代碼目的是替代Oracle的connect by語句,並實現后者的path和idleaf功能。
正文開始:
假設表org,字段有 id(編號),name(名稱),pid(上級編號), 最上級的記錄pid為空。
如:
id name pid
1 集團 null
2 財務部 1
3 行政部 1
4 主辦會計 2
實現目標表neworg:
id name pid pname path_id path_name leve is_leaf(葉子節點)
1 集團 null null /1 /集團 1 0
2 財務部 1 集團 /1/2 /集團/財務部 2 0
3 行政部 1 集團 /1/3 /集團/行政部 2 1
4 主辦會計 2 財務部 /1/2 /集團/財務部/主辦會計 2 1
代碼手寫,如有拼寫錯誤請見諒:
set gp_recursive_cte_prototype to ture; -- 部分低版本greenplum必須加 insert into neworg ( id, name, pid, path_id, path_name, leve, is_leaf ) with recursive result_ as -- 遞歸主體開始 ( select id -- 首先是頂層節點 , name , pid , cast(id as varchar(100)) as path_id -- 保證格式與目標表相同 , cast(name as varchar(500)) as path_name , 1 as leve from org where id = '1' -- 指定頂層節點位置 union all -- 下面是下層節點 select org.id , org.name , org.pid , cast(r.id || '/' || org.id as varchar(100)) as path_id -- 拼接時加上斜杠 , cast(r.name || '/' || org.name as varchar(500)) as path_name -- 拼接時加上斜杠 , r.leve + 1 as leve -- 每遞歸一次 + 1 , 0 as is_leaf from result_ r -- 注意這里是 result_ join org on org.pid = r.id -- 指定父子關系,這里注意其實是inner join where 1 = 1 -- 有其他條件可加在這里 ) -- 然后這里可以查詢result_了,同時加工is_leaf字段 select t.id, t.name, t.pid, org.name as pname , '/' || t.path_id as path_id -- 格式化避免頂層缺少斜杠 , '/' || t.path_name as path_name , t.leve , case when trim(t.id) in (select distinct a1.pid from org a1 ) then '0' else '1' and as id_leaf -- 判斷是否葉子節點,寫在此處當表數據量較大時效率較低,可以考慮額外跟新。 from result_ t left join org on t.pid = org.id -- 再關聯一下父級信息