【问题标题】:Oracle Hierarchical Query - extended info requiredOracle 分层查询 - 需要扩展信息
【发布时间】:2017-10-10 22:42:36
【问题描述】:


我有以下代表员工层次结构的数据,我需要确定员工/主管的所有可能排列。 我看过oracle Tree Walk,它似乎应该可以完成这项工作,但我不能完全让它发挥作用。问题是我需要为经理/员工的每个组合列出一行,这包括经理经理等。 (我已编辑添加要查询的名称)

有没有人知道如何做到这一点?

数据

SUPER SUP_NAME        EMP    EMP_NAME
^^^^^ ^^^^^^^          ^^^   ^^^^^^^
1     Big Boss         100   Sub Boss
100   Sub Boss         200   Field Boss
200   Field Boss       300   Field Emp

期望的结果

SUPER    EMP  SUP_NAME      EMP_NAME
^^^^^    ^^^  ^^^^^^^^      ^^^^^^^^
1        100   Big Boss     Sub Boss
1        200   Big Boss     Field Boss
1        300   Big Boss     Field Emp
100      200   Sub Boss     Field Boss
100      300   Sub Boss     Field Emp
200      300   Field Boss   Field Emp
300            Field Emp

【问题讨论】:

  • 到目前为止你尝试过什么查询 techGuy..?
  • 我刚刚尝试过 'Ponder Stibbons' (union) 的那个,它工作得很好,虽然我无法弄清楚将名字添加到其中的正确方法,因此编辑了原始问题以询问如何将名称拉过。
  • 现在更新了@ponderstibbons 的答案,包括修改后的超名列,empname 有效,请参阅最佳答案

标签: oracle hierarchical


【解决方案1】:

在标准分层查询中使用connect_by_root,并使用unionminus 添加不是经理的员工:

select connect_by_root(super) super, emp from data connect by super = prior emp
union
select emp, null from data minus select super, null from data

测试:

with data (super, emp) as (
    select   1, 100 from dual union all
    select 100, 200 from dual union all
    select 200, 300 from dual )
select connect_by_root(super) super, emp from data connect by super = prior emp
union
select emp, null from data minus select super, null from data

结果:

     SUPER        EMP
---------- ----------
         1        100
         1        200
         1        300
       100        200
       100        300
       200        300
       300 
7 rows selected

【讨论】:

  • 好答案!不过有两个建议:(1)使用 UNION ALL - 没有理由使用效率低得多的 UNION; (2) 使用 NOT IN 子句(反连接),而不是效率低得多的 MINUS 操作。
  • 您的解决方案非常有效,我使用了“Union”解决方案,感谢您的帮助。我试图添加主管姓名和员工姓名,但似乎无法正常工作,如何将它们添加到联合查询中?
  • @ponderstibbons - 更新您的答案以添加到我添加到原始查询的其他列中。
【解决方案2】:

试试这个查询。请注意,您需要在一行中包含 300, NULL 才能在结果集中包含 300, NULL

    WITH yourtable (super, emp )
     AS (SELECT 1,
                100
         FROM   dual
         UNION ALL
         SELECT 100,
                200
         FROM   dual
         UNION ALL
         SELECT 200,
                300
         FROM   dual
         UNION ALL
         SELECT 300,
                NULL
         FROM   dual),
     datatable
     AS (SELECT super,
                Ltrim(Sys_connect_by_path(emp, ','), ',') path
         FROM   yourtable
         START WITH emp IS NULL
         CONNECT BY PRIOR super = emp)
SELECT DISTINCT super,
                Regexp_substr(path, '[^,]+', 1, LEVEL) AS data
FROM   datatable
CONNECT BY Regexp_substr(path, '[^,]+', 1, LEVEL) IS NOT NULL
ORDER  BY super;  

【讨论】:

  • 也许这会奏效,但效率极低。正如@ponderstibbons 所展示的那样,请改用标准的分层查询功能。
  • @mathguy:是的。没有意识到connect_by_root(super)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多