我有一张桌子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
的行也为null
显示init
,那就没问题了。initname
列是完全可选的,我只在此处显示以供演示,我只需要id
。从我收集的关于 connect by
子句的内容中,我得到了一个相反的结果,其中列出了每个“root”的“子”节点。我不知道如何“打开查询”。
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');
答案 0 :(得分:3)
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.
答案 1 :(得分:1)
请尝试使用以下表达式获取根元素的名称:
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子句
答案 2 :(得分:0)
我设法通过嵌套查询获得结果。
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