给定层次结构中的任何子项,通过INFORMIX分层SQL获取完整树

时间:2016-05-30 06:06:04

标签: sql informix connect-by

我需要一些Informix层次结构sql查询的帮助。我有以下结构的表:

create table empl_relation (
employee_id char(10),
manager_id char(10));

employee_id      |   manager_id
 5148                null              
 5149                5148
 5150                5149
 5151                5148
 5152                5151
 5154                5148
 5155                5154

我能够成功运行以下查询:

SELECT employee_id, manager_id FROM empl_relation  
    START WITH employee_id = 5148 
    CONNECT BY PRIOR employee_id = manager_id 
    ORDER  SIBLINGS BY employee_id;

返回上表中指定的确切层次结构。但是,我想在这里尝试不同的东西。我试图获得相同的结果集,给定层次结构中的任何员工ID作为输入。例如,在查询中,如果我指定5154作为输入employee_id,我应该能够获得所有父母及其子女以及输入员工ID的子女和子女。确切地说,我想要通过运行上面提到的查询得到完全相同的结果集。

是否可以在单个查询中实现?如果是的话,你能帮助我实现这个目标吗?

                         EDIT

好的,我已经找到了实现这一目标的一种方法,但它涉及执行2个查询,如下所示:

SELECT employee_id, manager_id FROM empl_relation
    START WITH employee_id = 5150 
    CONNECT BY employee_id = PRIOR manager_id 
    ORDER   SIBLINGS BY employee_id ;

将返回:

employee_id      |   manager_id
5148    
5149                  5148
5150                  5149

然后我们可以通过遍历结果集然后执行以下查询来获取完整的分层树来检索应用层上的父employee_id:

SELECT employee_id, manager_id FROM empl_relation  
    START WITH employee_id = 5148 
    CONNECT BY PRIOR employee_id = manager_id 
    ORDER  SIBLINGS BY employee_id;

这样可以正常工作,但如果我能在单个查询中实现这一点,那真的很棒。

3 个答案:

答案 0 :(得分:2)

这将您的两个查询合并为一个,似乎有效:

SELECT employee_id, manager_id FROM empl_relation
 START WITH employee_id = (
                    SELECT h.employee_id
                      FROM (SELECT employee_id, manager_id
                              FROM empl_relation
                             START WITH employee_id = 5150
                           CONNECT BY employee_id = PRIOR manager_id
                           ) AS h
                     WHERE h.manager_id IS NULL)
CONNECT BY PRIOR employee_id = manager_id
 ORDER BY employee_id;

基本上,这会使您的查询在层次结构中运行并运行它,然后过滤结果以获得最高管理者(没有经理的员工),并将该值用作“顶层的层次下降”中的START查询。

5148
5149    5148
5150    5149
5151    5148
5152    5151
5154    5148
5155    5154

我得到的结果与任何起始值相同:5148,5149,5150,5151,5152,5154,5155。

答案 1 :(得分:2)

受Jonathan的回复启发,我提出了他的查询的简短版本,如下所示

SELECT employee_id,manager_id FROM empl_relation
START WITH employee_id =
 (SELECT employee_id
   FROM empl_relation er
   WHERE er.manager_id IS NULL
   START WITH employee_id = 5150 CONNECT BY employee_id =
   PRIOR manager_id) 
 CONNECT BY
 PRIOR employee_id = manager_id
 ORDER BY employee_id;

这似乎也很好。

答案 2 :(得分:0)

在informix 12 及更高版本中,您可以在临时表的帮助下使用简单的合并语句来实现所需的结果,而不是使用分层查询。

使用以下 stmt 创建临时表:

select a.employee_id,
       a.manager_id,
       rpad(a.manager_id, 100, ' ') as manager_hier,
       a.manager_id as topmanager
from empl_relation a
left join empl_relation b on a.manager_id = b.employee_id into temp emp_mgr_rel;

运行下面的合并 stmt 次数与树的最长分支的深度一样多。多运行它不会影响最终结果,所以不用担心:

merge into emp_mgr_rel as a using emp_mgr_rel as b on a.topmanager = b.employee_id WHEN MATCHED THEN
UPDATE
set a.manager_hier = nvl(trim(a.manager_hier), '') || '-' || nvl(trim(b.topmanager), ''),
    a.topmanager = trim(b.manager_hier);

使用以下 stmt 检查您的结果。您将在 manager_hier 列下看到作为带连字符的值的层次结构:

select employee_id, manager_hier from emp_mgr_rel;