[英]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.