展平层次结构查询PLSQL,不使用子查询和函数

时间:2018-07-20 14:32:00

标签: oracle plsql hierarchy

我是PLSQL的新手,并开始学习如何以有效的方式编写查询。在使用Connect By简化员工报告层次结构方面,我面临着挑战。

  1. 当前,我们在员工报告中具有五个层次结构,但是我们的查询不应限于五个层次。将来,如果我们有新的报告要求,则可以在不进行任何更改的情况下使用相同的查询。

  2. 结果集中的所有记录应在同一级别结束,如果Manager没有向其报告的员工,则5级应该是经理本身。您可以看到下面的预期结果,以更好地理解。示例:Mgr1和Mgr3

注意:为了获得更好的性能,我不想为此请求使用任何函数或子查询。

预期结果:

Level 1     Level 2     Level 3 Level 4 Level 5 **(Level 6, Level 7 ) for future**
----------  ----------  ------- ------- ------ ------ -------
President   VP1         Dir1    Mgr1    Mgr1        
President   VP1         Dir2    Mgr2    Emp1        
President   VP2         Dir3    Mgr4    Emp2        
President   VP2         Dir4    Mgr3    Mgr3        
President   VP3         Dir5    Mgr5    Emp3        
President   VP3         Dir6    Mgr6    Emp4        
President   VP4         Dir7    Mgr7    Emp5

1 个答案:

答案 0 :(得分:1)

对我来说,以下内容类似于您想要的内容:

with normalized$(super_id, emp_id) as (
    select null, 'president' from dual
    union all
    select 'president', 'vp1' from dual
    union all
    select 'president', 'vp2' from dual
    union all
    select 'president', 'vp3' from dual
    union all
    select 'president', 'vp4' from dual
    union all
    select 'vp1', 'dir1' from dual
    union all
    select 'vp1', 'dir2' from dual
    union all
    select 'vp2', 'dir3' from dual
    union all
    select 'vp2', 'dir4' from dual
    union all
    select 'vp3', 'dir5' from dual
    union all
    select 'vp3', 'dir6' from dual
    union all
    select 'vp4', 'dir7' from dual
    union all
    select 'dir1', 'mgr1' from dual
    union all
    select 'dir2', 'mgr2' from dual
    union all
    select 'dir3', 'mgr4' from dual
    union all
    select 'dir4', 'mgr3' from dual
    union all
    select 'dir5', 'mgr5' from dual
    union all
    select 'dir6', 'mgr6' from dual
    union all
    select 'dir7', 'mgr7' from dual
    union all
    select 'mgr2', 'emp1' from dual
    union all
    select 'mgr4', 'emp2' from dual
    union all
    select 'mgr5', 'emp3' from dual
    union all
    select 'mgr6', 'emp4' from dual
    union all
    select 'mgr7', 'emp5' from dual
    union all
    -- note: these two are added here for testing the levels 6 and 7
    select 'emp2', 'sub1' from dual
    union all
    select 'sub1', 'subsub1' from dual
),
denormalized$ as (
    select ora_hash(emp_id) as hierarchy_id, -- note: this is just "some" row id; use whatever else you wish
        sys_connect_by_path(emp_id, '|') as hierarchy
    from normalized$ N
    where connect_by_isleaf = 1
    start with super_id is null
    connect by prior emp_id = super_id
),
split$ as (
    select hierarchy_id,
        regexp_substr(hierarchy, '\|([^|]*)', 1, 1, null, 1) as h_lvl_1,
        regexp_substr(hierarchy, '\|([^|]*)', 1, 2, null, 1) as h_lvl_2,
        regexp_substr(hierarchy, '\|([^|]*)', 1, 3, null, 1) as h_lvl_3,
        regexp_substr(hierarchy, '\|([^|]*)', 1, 4, null, 1) as h_lvl_4,
        regexp_substr(hierarchy, '\|([^|]*)', 1, 5, null, 1) as h_lvl_5,
        regexp_substr(hierarchy, '\|([^|]*)', 1, 6, null, 1) as h_lvl_6,
        regexp_substr(hierarchy, '\|([^|]*)', 1, 7, null, 1) as h_lvl_7
    from denormalized$
),
filled$ as (
    select hierarchy_id,
        h_lvl_1,
        coalesce(h_lvl_2, h_lvl_1) as h_lvl_2,
        coalesce(h_lvl_3, h_lvl_2, h_lvl_1) as h_lvl_3,
        coalesce(h_lvl_4, h_lvl_3, h_lvl_2, h_lvl_1) as h_lvl_4,
        coalesce(h_lvl_5, h_lvl_4, h_lvl_3, h_lvl_2, h_lvl_1) as h_lvl_5,
        coalesce(h_lvl_6, h_lvl_5, h_lvl_4, h_lvl_3, h_lvl_2, h_lvl_1) as h_lvl_6,
        coalesce(h_lvl_7, h_lvl_6, h_lvl_5, h_lvl_4, h_lvl_3, h_lvl_2, h_lvl_1) as h_lvl_7
    from split$
)
select *
from filled$
;

...屈服...

HIERARCHY_ID H_LVL_1   H_LVL_2 H_LVL_3 H_LVL_4 H_LVL_5 H_LVL_6 H_LVL_7
------------ --------- ------- ------- ------- ------- ------- -------
   490409852 president vp1     dir1    mgr1    mgr1    mgr1    mgr1
  1220769441 president vp1     dir2    mgr2    emp1    emp1    emp1
   849214331 president vp2     dir3    mgr4    emp2    sub1    subsub1
   530886880 president vp2     dir4    mgr3    mgr3    mgr3    mgr3
  1157603336 president vp3     dir5    mgr5    emp3    emp3    emp3
  1467614544 president vp3     dir6    mgr6    emp4    emp4    emp4
   523144703 president vp4     dir7    mgr7    emp5    emp5    emp5

但是,(我知道)您不可能(没有返回sys.anyDataSet的表函数)可能进行查询以返回任意数量的列,所以我们坚持假设您的层次结构中有一些最大的最大数量,在上面的查询为7的情况下。

请注意,即使没有相对较慢的正则表达式,也可以以不同的方式完成按路径进行连接及其后续拆分。检查自己的方式,选择最适合自己的方式。