Bootstrap

递归公用表达式(子查询因子化)查询父代或子代(层次结构)

就是一道遇到的面试题,其实很简单。只是当时可能相对比较紧张没有好好写出来。
查询某个节点的子代
为了方便我借用Oracle中的Scott模式下的emp表
emp查询结果
下图显示了人员信息层次结构

WITH CTE(EmpNo,Mgr,EName,LVL)
AS
(
SELECT EmpNo,Mgr,EName,0 LVL
FROM Scott.Emp
WHERE Mgr IS NULL
UNION ALL
SELECT t.empno,t.mgr,t.ename,t1.LVL+1 LVL
FROM Scott.Emp t
INNER JOIN CTE t1 ON t.mgr=t1.EmpNo
)
SEARCH DEPTH FIRST BY EmpNo SET ORDER1

SELECT LPAD(' ',LVL*2,' ')||EName EName,LVL,EmpNO,Mgr FROM CTE;

人员信息层次结构述
当时我就一直想怎么利用这个CTE再来查询出一个人员的子代呢,实现没有简单(一个语句)方法实现,最后放弃了。
回来以后想想其实就是当时的惯性思维写这个把整个的人员层次结构都查出来,那要查询某个人子代,不是就某个人层次结构了么(改了加粗与斜体的地方)

WITH CTE(EmpNo,Mgr,EName,LVL)
AS
(
SELECT EmpNo,Mgr,EName,0 LVL
FROM Scott.Emp
***WHERE EName='JONES'***
UNION ALL
SELECT t.empno,t.mgr,t.ename,t1.LVL+1 LVL
FROM Scott.Emp t
INNER JOIN CTE t1 ON t.mgr=t1.EmpNo
)
SEARCH DEPTH FIRST BY EmpNo SET ORDER1

SELECT LPAD(' ',LVL*2,' ')||EName EName,LVL,EmpNO,Mgr FROM CTE;

某个人员下面的层次结构(子代)

检索某个节点的父代也就相对简单了(修改加粗处)

WITH CTE(EmpNo,Mgr,EName,LVL)
AS
(
SELECT EmpNo,Mgr,EName,0 LVL
FROM Scott.Emp
**WHERE EName='SMITH'**
UNION ALL
SELECT t.empno,t.mgr,t.ename,t1.LVL+1 LVL
FROM Scott.Emp t
**INNER JOIN CTE t1 ON t.empno=t1.Mgr**
)
SEARCH DEPTH FIRST BY EmpNo SET ORDER1

SELECT LPAD(' ',LVL*2,' ')||EName EName,LVL,EmpNO,Mgr FROM CTE;

节点父层次结构
上面显示格式没有进行调整,是从子代向父代(从上向下)。根据需要重新进行格式化设置。

;