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

Flatten a hierarchy query PLSQL not using subqueries and functions

我是 PLSQL 的新手,开始学习如何高效地编写查询。我面临着使用 Connect By 扁平化员工报告层次结构的挑战。

  1. 目前,我们在员工报告中有五个级别的层次结构,但我们的查询不应限制为 5 个级别。将来,如果我们有新的报告级别,相同的查询应该可以在不做任何更改的情况下工作。

  2. 结果集中的所有记录都应该在同一级别结束,如果经理没有向 him/her 报告的员工,那么级别 5 应该是经理本身。您可以看到下面的预期结果以便更好地理解。示例:经理 1 和经理 3

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

预期结果:

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

对我来说,以下看起来像你想要的:

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

但是,没有办法(我知道)你可以(没有 table 函数 returning sys.anyDataSet)可能对 return 任意列数的查询,所以让我们只坚持层次结构中假定的最大级别数,如果上面的查询是 7.

注意 可以通过不同的方式完成按路径连接及其后续拆分 - 即使没有相对较慢的正则表达式。审视自己的方式,选择最适合自己的方式。