我是PLSQL的新手,并开始学习如何以有效的方式编写查询。在使用Connect By简化员工报告层次结构方面,我面临着挑战。
当前,我们在员工报告中具有五个层次结构,但是我们的查询不应限于五个层次。将来,如果我们有新的报告要求,则可以在不进行任何更改的情况下使用相同的查询。
结果集中的所有记录应在同一级别结束,如果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
答案 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的情况下。
请注意,即使没有相对较慢的正则表达式,也可以以不同的方式完成按路径进行连接及其后续拆分。检查自己的方式,选择最适合自己的方式。