5

给定树的节点,如何找到整棵树?

树的例子:

       100
  101        102
1010 1011   1020  1021


select level, employee_id, last_name, manager_id ,
       connect_by_root employee_id as root_id
  from employees
 connect by prior employee_id = manager_id
 start with employee_id = 101
;

表中的根是 (parent,child) 示例 (100,101) 表中没有 (null,100) 行。

上面的查询只给了从 101 开始的孩子。但是假设我想要从根开始的所有东西?

当给定“101”作为节点时,您将不知道哪个是根。

当根是给定节点时,查询应该可用。

4

3 回答 3

7

您需要首先遍历树以获取所有经理,然后向下遍历以获取所有员工:

select level, employee_id, last_name, manager_id ,
       connect_by_root employee_id as root_id
   from employees
connect by prior employee_id = manager_id -- down the tree
start with manager_id in ( -- list up the tree
     select manager_id 
       from employees
     connect by employee_id = prior manager_id -- up the tree
     start with employee_id = 101
     )
;

http://www.sqlfiddle.com/#!4/d15e7/18

编辑:

如果给定节点也可能是根节点,则扩展查询以将给定节点包含在父节点列表中:

非根节点示例:

select distinct employee_id, last_name, manager_id 
   from employees
connect by prior employee_id = manager_id -- down the tree
start with manager_id in ( -- list up the tree
     select manager_id 
       from employees
     connect by employee_id = prior manager_id -- up the tree
     start with employee_id = 101
     union 
     select manager_id -- in case we are the root node
       from employees
     where manager_id = 101
     )
;

根节点示例:

select distinct employee_id, last_name, manager_id 
   from employees
connect by prior employee_id = manager_id -- down the tree
start with manager_id in ( -- list up the tree
     select manager_id 
       from employees
     connect by employee_id = prior manager_id -- up the tree
     start with employee_id = 100
     union 
     select manager_id -- in case we are the root node
       from employees
     where manager_id = 100
     )
;

小提琴http://www.sqlfiddle.com/#!4/d15e7/32

于 2012-07-24T06:29:16.037 回答
6

为什么不只是:

select level, employee_id, last_name, manager_id ,
connect_by_root manager_id as root_id
from employees
connect by prior employee_id = manager_id
start with manager_id = 100

是一个小提琴

编辑
这是另一个尝试(在了解完整问题后):

with t as (
select case when mgr.employee_id is null then
1 else 0 end is_root, emp.employee_id employee, emp.manager_id manager, emp.last_name last_name

from employees mgr right outer join employees emp
on mgr.employee_id = emp.manager_id
),
tmp as (

select level, employee, last_name, manager ,
connect_by_root manager as root_id,
manager||sys_connect_by_path(employee,
',') cbp

from t
connect by prior employee = manager
start with t.is_root =
1 )
select * from tmp
where tmp.root_id in (select root_id from tmp where employee= 101 or manager = 101)

我检查了它,100它运行良好是一个小提琴1011010

于 2012-07-24T05:36:17.990 回答
1
select 
     level, 
     employee_id, 
     last_name, manager_id ,
connect_by_root employee_id as root_id
from employees
connect by prior employee_id = manager_id
start with employee_id in  ( 
  select employee_id from employees 
  where manager_id is null )
于 2014-02-21T08:58:30.080 回答