【问题标题】:Oracle Hierarchical query: how to include top-level parentOracle 分层查询:如何包含顶级父级
【发布时间】:2009-05-21 14:09:12
【问题描述】:

我有一个分层查询来跟踪报告结构。这几乎可行,只是它没有报告最顶层的节点,可能是因为顶层的人“报告”给自己。

查询是:

select
  level,
  empid, 
  parentid
from usertable
connect by nocycle prior parentid= empid
start with empid = 50

这会产生:

LEVEL  EMPID PARENTID               
------ ----- --------  
1      50    258            
2      258   9555
3      9555  17839

我没有达到 4 级,因为它看起来像:

4      17839 17839

在不更改数据的情况下,有没有办法修改我的查询以返回所有 4 个级别?目标是得到 empids,所以我可以检查一下

id in (hierarchical subquery)

顺便说一句,如果我从查询中删除 nocycle,我会收到错误。

【问题讨论】:

    标签: oracle hierarchical-data


    【解决方案1】:

    克里斯,

    您只会得到 3 行,因为您的顶级行未设置为处理分层查询的方式。通常,Oracle 著名的 EMP 表中的顶级行或总裁 KING 没有经理。在您的情况下,您不应将 17389 的 parentid 设置为 17389 本身,而应设置为 NULL。要么相应地更新表格,要么使用视图来适应这种情况。

    一个例子:

    SQL> select empno
      2       , mgr
      3    from emp
      4   where empno in (7876,7788,7566,7839)
      5  /
    
         EMPNO        MGR
    ---------- ----------
          7566       7839
          7788       7566
          7839       7839
          7876       7788
    
    4 rijen zijn geselecteerd.
    

    EMP 表的这一部分有四个级别,其顶层行 (7839) 设置为自身。与您的 empid 17839 相同。这会导致使用您的查询仅三行:

    SQL>  select level
      2        , empno
      3        , mgr
      4     from emp
      5  connect by nocycle prior mgr = empno
      6    start with empno = 7876
      7  /
    
         LEVEL      EMPNO        MGR
    ---------- ---------- ----------
             1       7876       7788
             2       7788       7566
             3       7566       7839
    
    3 rijen zijn geselecteerd.
    

    要么使用(内联)视图将顶级的 mgr/parentid 列设置为 null:

    SQL>  select level
      2        , empno
      3        , mgr
      4     from ( select empno
      5                 , nullif(mgr,empno) mgr
      6              from emp
      7          )
      8  connect by nocycle prior mgr = empno
      9    start with empno = 7876
     10  /
    
         LEVEL      EMPNO        MGR
    ---------- ---------- ----------
             1       7876       7788
             2       7788       7566
             3       7566       7839
             4       7839
    
    4 rijen zijn geselecteerd.
    

    或者使用 UPDATE 语句修复您的数据:

    SQL> update emp
      2     set mgr = null
      3   where empno = 7839
      4  /
    
    1 rij is bijgewerkt.
    
    SQL>  select level
      2        , empno
      3        , mgr
      4     from emp
      5  connect by nocycle prior mgr = empno
      6    start with empno = 7876
      7  /
    
         LEVEL      EMPNO        MGR
    ---------- ---------- ----------
             1       7876       7788
             2       7788       7566
             3       7566       7839
             4       7839
    
    4 rijen zijn geselecteerd.
    

    您也可以在完成修复后省略 NOCYCLE 关键字。

    问候, 抢。

    【讨论】:

      【解决方案2】:

      你需要反过来做层次结构,从根到叶。

      select
        level,
        empid, 
        parentid
      from usertable
      start with empid = 17839
      connect by empid != 17839 and prior empid = parentid
      
      LEVEL                  EMPID                  PARENTID               
      ---------------------- ---------------------- ---------------------- 
      1                      17839                  17839                  
      2                      9555                   17839                  
      3                      258                    9555                   
      4                      50                     258                    
      
      4 rows selected
      

      【讨论】:

      • 不幸的是,这行不通。顶层会有一堆 2 级,但我只想要 4 级以上的层次结构中的 2 级。想想员工、经理、主管、副总裁 - 主管和副总裁可以看到员工创建的数据,但另一个经理不能向该主管报告。
      【解决方案3】:

      你不必改变你的结构。

      只需使用以下查询

      select
        level,
        empid,
        parentid
      from usertable
      connect by prior parentid = empid
             AND parentid <> empid  -- This line prohibits cycling and ALLOWS a row where parentid = empid
      start with empid = 50
      

      【讨论】:

        【解决方案4】:

        Van Heddegem Roeland 的回答对我不起作用,我已经尝试过了,但我设法在没有内联视图的情况下在连接子句中通过添加:-

        and prior empid <> parentid
        

        下面的帖子解释了为什么它有效 - 如果你能理解它!虽然一旦你“明白”它确实合乎逻辑。 (这与 运算符每一侧的求值顺序有关。)

        Oracle: Connect By Loop in user data

        内联视图可以工作,但如果不对您的特定数据集进行研究,我不知道内联视图可能会对查询路径产生什么影响。在大多数情况下,添加额外的子句可能是“正确”的方式,恕我直言。

        【讨论】:

          【解决方案5】:

          您的数据似乎有一个循环。没有“nocycle”,它不会立即工作。如果您知道所有数据的最大嵌套级别为 4,那么您可以添加条件“和级别

          【讨论】:

          • 不幸的是,嵌套级别会有所不同。
          猜你喜欢
          • 2022-01-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-08-20
          相关资源
          最近更新 更多