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

Oracle 不使用子查询和函数展平层次查询PLSQL,oracle,plsql,hierarchy,Oracle,Plsql,Hierarchy,我是PLSQL新手,并开始学习如何以高效的方式编写查询。我面临着一个挑战,那就是如何使用Connect By将员工报告层次结构扁平化 目前,我们在员工报告中有五个层次,但我们的查询不应限制为5个层次。将来,如果我们有新的lvel报告,相同的查询应该在不做任何更改的情况下工作 结果集中的所有记录应以同一级别结束,如果经理没有向他/她报告的员工,则第5级应为经理本身。为了更好地理解,您可以看到以下预期结果。示例:Mgr1和Mgr3 注意:为了获得更好的性能,我不想对此请求使用任何函数或子查询 预期结

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

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

  • 结果集中的所有记录应以同一级别结束,如果经理没有向他/她报告的员工,则第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
    

    在我看来,以下内容与您想要的一样:

    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,我们只需坚持您的层次结构中假定的最大级别数


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

    您的示例不太清楚,如果正确格式化和对齐,并显示源数据,会有所帮助。如果要使用connect by,为什么要使用PL/SQL?为什么第6/7层是空的?根据您之前的逻辑,第一行的第6层和第7层条目不应该都是Mgr1吗?很抱歉,会解决这个问题并尝试改进格式,我们必须使用Connect解决这个问题,不限于PL/SQL,我只是保留了这两个级别(第6层和第7层)以供理解,在未来的Emp5中,可能会有一名进入6级的报告者,以此类推。。即使在这种情况下,我们的查询也会起作用。然后结果集中的所有其他行的第5级值都会重复为第6级?请编辑您的问题,以包含反映您期望得到的输出的示例输入数据?编写“按查询连接”很简单(此站点按原样)。然而,默认悬垂叶子的要求非常严格,我不知道如果没有函数或子查询,你怎么能做到这一点。那么,这是你家庭作业的实际要求还是你对自己施加的额外限制?谢谢你在这方面的帮助