SQL 找出给定的父节点对应的所有子节点,你想找出 JONES 的下属员工,既包括直接的下属,也包括间接的下属(即这些员工的管理者是 JONES 的下属)。JONES 的所有下属显示如下。
SQL 找出给定的父节点对应的所有子节点 问题描述
你想找出 JONES 的下属员工,既包括直接的下属,也包括间接的下属(即这些员工的管理者是 JONES 的下属)。JONES 的所有下属显示如下。(JONES 本人也会包含在该结果集中。)
SQL 找出给定的父节点对应的所有子节点 解决方案
能够自由移动到树形结构的顶端或底端是非常有用的一项特性。本解决方案并不要求做特殊的格式化工作。我们的目标只是要显示 JONES 的所有下属,也包括 JONES 本人。这种类型的查询往往能体现出 SQL 递归特性的优势,例如,Oracle 的 CONNECT BY
子句,SQL Server 和 DB2 的 WITH
子句。
DB2 和 SQL Server
使用 WITH
递归查询找出 JONES 的下属。UNION
查询的前半部分,通过指定 WHERE ENAME = 'JONES'
表明递归操作从 JONES
开始。
Oracle
使用 CONNECT BY
子句,并指定 START WITH ENAME = 'JONES'
找出 JONES 的所有下属。
PostgreSQL 和 MySQL
我们必须先计算出树形结构包含了多少个节点,下面的查询展示了如何确定层次关系的深度。
该层次关系起始于 JONES,终止于 SMITH 和 ADAMS。它的深度为 3 层。既然已经知道了深度,我们就可以从顶端到底端依次遍历整个层次关系。
首先,2 次自连接 EMP
表。然后转换内嵌视图 X
把 2 行 3 列的数据集变为 6 行 1 列。(对于 PostgreSQL 而言,还有另一种做法,即可以使用 GENERATE_SERIES(1,6)
来代替数据透视表 T100
。)
除此之外,我们还可以使用视图,并把视图的结果集 UNION
起来。我们创建了一些视图,如下所示。
因而,本解决方案将就变成了下面的查询。
SQL 找出给定的父节点对应的所有子节点 扩展知识
DB2 和 SQL Server
WITH
递归查询使得本问题解决起来容易多了。WITH
子句的第一部分,即 UNION ALL
的前半部分,返回了员工 JONES 所在的行。我们需要返回 ENAME
以得到员工的名字,并返回 EMPNO
以便基于它做连接查询。UNION ALL
的后半部分基于 EMP.MGR
和 X.EMPNO
做递归的连接查询。该连接条件将一次次地执行下去,直至遍历完整个结果集。
Oracle
START WITH
子句表明查询操作将以 JONES 为根节点。CONNECT BY
子句的条件驱动树形结构的遍历操作,并将一直执行下去,直到条件不再成立才会停止。
PostgreSQL 和 MySQL
本解决方案最显而易见的不足是,我们需要提前知道层次关系的深度。