我有一个如下表:
ID PARENT_ID
--- ----------
1 null
2 1
3 2
4 2
5 4
6 4
7 1
8 7
9 1
10 9
11 10
12 9
13 null
14 13
我想查询这样的结果:
ID | PARENT_ID
-----+-----------
1 | 1
2 | 1
2 | 2
3 | 1
3 | 2
3 | 3
4 | 1
4 | 2
4 | 4
5 | 1
5 | 2
5 | 4
5 | 5
...
我使用Oracle connected by root
并得到以下结果:
ID PATH
--- -----------
1 1
2 1-2
3 1-2-3
4 1-2-4
5 1-2-4-5
....
但这不是我想要的。
还有没有其他方法可以通过表获得相同的结果而无需通过root进行连接(在标准SQL中首选)吗?
有人可以帮助我吗?
注意:我使用的是Oracle数据库
谢谢
答案 0 :(得分:1)
第一步是进行查询,该查询将为您生成特定节点上方的所有父级。
以下是此类查询的示例:
select * from
(SELECT parent_id
FROM test
START WITH ID = 4
CONNECT BY ID = PRIOR PARENT_ID) temp
where parent_id is not null
UNION
select ID from test where ID = 4 ;
在上述情况下,我们从节点4开始。
下一步是使用此查询,并使用另一个查询来获取所有节点的结果。
(很快就会产生)
create table test(
id int,
parent_id int
);
insert into test values (1, null);
insert into test values (2,1);
insert into test values (3,2);
insert into test values (4,2);
select distinct ID, parent_id from
(
SELECT a.parent_id as aParent, b.parent_id as bParent, b.id as ID, a.id as parent_id
FROM test a, test b
START WITH a.ID = b.id
CONNECT BY a.ID = PRIOR a.PARENT_ID
) temp
where not (aParent is not null AND bParent is null)
order by id, parent_id;
SELECT distinct b.id as ID, a.id as parent_id
FROM test a, test b
where not (a.parent_id is not null and b.parent_id is null )
START WITH a.ID = b.id
CONNECT BY a.ID = PRIOR a.PARENT_ID order by id, parent_id;;
SELECT distinct
findNodesAboveMe.id as ID,
pathFollowing.id as parent_id
FROM
test pathFollowing,
test findNodesAboveMe
where
pathFollowing.parent_id is null
OR findNodesAboveMe.parent_id is not null START WITH pathFollowing.ID = findNodesAboveMe.id CONNECT BY pathFollowing.ID = PRIOR pathFollowing.PARENT_ID
order by
id,
parent_id;
select id, parent_id from
(
(SELECT DISTINCT
findNodesAboveMe.id AS ID,
CASE WHEN pathFollowing.parent_id IS NULL
THEN pathFollowing.id
ELSE pathFollowing.parent_id END AS parent_id
FROM
test pathFollowing,
test findNodesAboveMe
WHERE
findNodesAboveMe.parent_id IS NOT NULL
START WITH pathFollowing.ID = findNodesAboveMe.id CONNECT BY pathFollowing.ID = PRIOR pathFollowing.PARENT_ID
)
UNION
SELECT
id,
id AS parent_id
FROM test
) order by id, parent_id
;
select
distinct bid as ID, aid as parent_id
from
(
SELECT DISTINCT
a.id as aid,
a.parent_id as aparentid,
b.id as bid,
b.parent_id as bparentid,
ltrim(sys_connect_by_path(a.id, ','), ',') AS pth
FROM test a, test b
WHERE NOT
(a.parent_id IS NOT NULL AND b.parent_id IS NULL)
START WITH a.ID = b.id
CONNECT BY a.ID = PRIOR a.PARENT_ID
) temp
where ( pth like bid or pth like bid || ','|| bparentid || '%' )
order by ID, parent_id;