繁体   English   中英

如何通过CONNECT BY查询到达“最终的前身”?

[英]How to get to the “final predecessor” with a CONNECT BY query?

我有一个表, SELECT * FROM data

id   pred   name        visual link, for your convenience
--------------------
 1   null   One              
20   null   Two         <--+
21     20   Three         -^
30   null   Four              <--+      
31     30   Five                -^  <--+ 
32     31   Six                       -^  

其中行通过pred列连接到id列。 它们仅形成链而不是树-每个节点只有一个或零个后继(如果重要的话)。

我想在显示链中第一个元素的查询中添加列init ,即

id   pred   name    init initname
---------------------------------
 1   null   One        1 One
20   null   Two       20 Two
21     20   Three     20 Two
30   null   Four      30 Four
31     30   Five      30 Four
32     31   Six       30 Four
  • 如果具有pred=null行也为init显示null ,那将是可以的。
  • initname列是完全可选的,在这里仅出于演示目的显示它,我只需要id

connect by收集关于connect by子句的信息,我得到了一个相反的结果,其中为每个“根”列出了其“子”节点。 我不知道如何“扭转查询”。

SELECT id, pred, CONNECT_BY_ROOT id init, LEVEL, CONNECT_BY_ISLEAF "IsLeaf"
FROM data
CONNECT BY PRIOR pred=id
ORDER BY id, level;

给出结果

id  pred   init lvl isLeaf
--------------------------
1   null    1   1   1
20  null    20  1   1
20  null    21  2   1
21  20      21  1   0
30  null    30  1   1
30  null    31  2   1
30  null    32  3   1
31  30      31  1   0
31  30      32  2   0
32  31      32  1   0

显然,它以某种方式代表了整个“树”。 但是可惜,“绕错路了”。 我需要例如

id  pred  init lvl isLeaf
21   20    0     ?   ?

代替

id  pred init lvl isLeaf
21   20   21   1     0

如果需要数据,请参见以下示例数据:

create table data ( id number primary key, pred number, name varchar2(100) );
insert into data(id,pred,name) values(     1 ,  null  , 'One');
insert into data(id,pred,name) values(    20,   null  , 'Two');
insert into data(id,pred,name) values(21,     20  , 'Three');
insert into data(id,pred,name) values(30,   null ,  'Four');
insert into data(id,pred,name) values(31,     30 ,  'Five');
insert into data(id,pred,name) values(32,     31 ,  'Six');
SQL>  select id
  2        , pred
  3        , name
  4        , connect_by_root id             init
  5        , connect_by_root name           initname
  6        , sys_connect_by_path(id,' -> ') scbp
  7     from data
  8  connect by prior id = pred
  9    start with pred is null
 10  /

        ID       PRED NAME             INIT INITNAME   SCBP
---------- ---------- ---------- ---------- ---------- ------------------------------
         1            One                 1 One         -> 1
        20            Two                20 Two         -> 20
        21         20 Three              20 Two         -> 20 -> 21
        30            Four               30 Four        -> 30
        31         30 Five               30 Four        -> 30 -> 31
        32         31 Six                30 Four        -> 30 -> 31 -> 32

6 rows selected.

请尝试使用以下表达式获取根元素的名称:

substr(SYS_CONNECT_BY_PATH(name, '/'), instr(SYS_CONNECT_BY_PATH(name, '/'), '/', -1)+1)

如果需要,请替换定界符“ /”。

SELECT id, pred, CONNECT_BY_ROOT id init, LEVEL, CONNECT_BY_ISLEAF "IsLeaf", 
       substr(SYS_CONNECT_BY_PATH(name, '/'), instr(SYS_CONNECT_BY_PATH(name, '/'), '/', -1)+1)
FROM data
CONNECT BY PRIOR pred=id
--    START WITH pred is NULL --???
ORDER BY id, level;

您可能还需要添加START WITH子句

我设法通过嵌套查询得到结果。

select id, pred, name, init, (select name from data where id=init) initname
from (
    SELECT d1.*
      , (select d2.id init
           from data d2
         where CONNECT_BY_ISLEAF=1 start with d2.id=d1.id CONNECT BY PRIOR pred=id) init
    FROM data d1
    ORDER BY id ) xdata
;

如您所见,要获取initname我需要以这种方式进行其他子查询。 这不是完美的,但足够好-查询位于PK上。

id pred Name    init initname
------------------------------
1       One     1    One
20      Two     20   Two
21  20  Three   20   Two
30      Four    30   Four
31  30  Five    30   Four
32  31  Six     30   Four

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM