我知道如何使用connect by
像这样导航层次结构:
SELECT RPAD ('*', 2 * LEVEL, '*') || ename ename, empno
FROM scott.emp
START WITH mgr IS NULL
CONNECT BY PRIOR empno = mgr
现在我想使用递归with
子句向后走树,但我无法弄清楚如何这样做。
请帮助我。
答案 0 :(得分:0)
关于递归WITH语法有两个棘手的问题。
我们在第二个查询中定义了两个查询,一个作为锚点(START WITH值)和一个UNION ALL,它检索层次结构的子节点。
另一个问题是我们不能使用LEVEL在CONNECT BY查询中生成填充(因为我们没有使用CONNECT BY)。因此,我们添加另一列以在我们导航树时保持级别的计数。请注意,我从0开始,因此层次结构的顶部没有用星号填充。
因此,这是您的查询重新转换为递归的WITH语句:
with e1 (ename, empno, lvl)
as ( select ename
, empno
, 0 as lvl
from emp
where mgr is null
union all
select e2.ename
, e2.empno
, e1.lvl + 1
from emp e2, e1
where e2.mgr = e1.empno )
search depth first by empno set empno_order
select rpad ('*', 2 * e1.lvl, '*') || e1.ename ename
, e1.empno
from e1
order by empno_order
;
search depth first
子句保证结果集在显示兄弟节点之前显示给定节点的所有子节点。 (search breadth first
将列出所有兄弟姐妹然后从层次结构的下一级开始。)
现在,要做一个反向树步行,我们需要从不是经理的员工开始。因为我们正在检查空值,所以我们需要使用NOT EXISTS而不是NOT IN。否则查询几乎相同;我选择显示MGR而不是EMPNO,但您可能更愿意还原。
with e1 (ename, mgr, lvl)
as ( select e.ename
, e.mgr
, 0 as lvl
from emp e
where not exists ( select null
from emp x
where x.mgr = e.empno)
union all
select e2.ename
, e2.mgr
, e1.lvl + 1
from emp e2, e1
where e2.empno = e1.mgr )
search depth first by mgr set mgr_order
select rpad ('*', 2 * e1.lvl, '*') || e1.ename ename
, e1.mgr
from e1
order by mgr_order
;
以下是此查询的示例输出:
ENAME MGR
------------------------------ ----------
ALLEN 7698
**BLAKE 7839
****KING
JAMES 7698
**BLAKE 7839
****KING
MARTIN 7698
**BLAKE 7839
****KING
TURNER 7698
...