2

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

查询是:

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,我会收到错误消息。

4

5 回答 5

5

克里斯,

您只得到 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 关键字。

问候,罗布。

于 2009-05-21T15:17:29.383 回答
3

您需要以相反的方式进行层次结构,从根到叶。

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
于 2009-05-21T14:30:17.670 回答
1

你不必改变你的结构。

只需使用以下查询

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
于 2010-12-10T09:44:45.457 回答
1

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

and prior empid <> parentid

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

Oracle:在用户数据中按循环连接

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

于 2016-01-06T10:51:08.683 回答
-1

好像你有一个数据周期。没有“nocycle”,它不会立即工作。如果您知道所有数据的最大嵌套级别为 4,那么您可以添加条件“和级别 <= 4”并删除 nocycle。应该管用。

于 2009-05-21T14:32:52.920 回答