Sql 如何查询(几乎)树结构

Sql 如何查询(几乎)树结构,sql,database,oracle,Sql,Database,Oracle,嗨,我有这张桌子: id replacement id 1 2 2 1 2 3 3 2 2 4 4 2 10 11 11 10 id valid_until 1 2 2014-01-01 3 2013-01-01 4 2013-01-01 10 11 2014-01-01 IDObject是树状结构,但表的树状结构设计得很差。 节点之间的连接是双向的 确定一个是否为另一个的父级的唯一方法是使用以下表格: id

嗨,我有这张桌子:

id   replacement id
1     2
2     1
2     3
3     2
2     4
4     2
10    11
11    10
id  valid_until
1
2   2014-01-01
3   2013-01-01
4   2013-01-01
10  
11  2014-01-01
IDObject是树状结构,但表的树状结构设计得很差。 节点之间的连接是双向的

确定一个是否为另一个的父级的唯一方法是使用以下表格:

id   replacement id
1     2
2     1
2     3
3     2
2     4
4     2
10    11
11    10
id  valid_until
1
2   2014-01-01
3   2013-01-01
4   2013-01-01
10  
11  2014-01-01
2是3和4的父项,因为它的有效_-until晚于3和4。1是顶部节点,因为它仍然有效

我正在努力编写此数据的查询,以便它看起来像这样:

id  parent
1
2   1
3   2
4   2 
是否有一种方法可以将其作为单个查询,或者我必须为此创建一个过程和一个临时视图


编辑:我在表格中添加了一些新行。所以基本上我还想在查询中说,我只想要id:1,2,3或4的树,而不是10和11。我该怎么做呢?

我相信这会奏效的

create table a (id number, rid number);

insert into a values(1,2);
insert into a values(2,1);
insert into a values(2,3);
insert into a values(3,2);
insert into a values(2,4);
insert into a values(4,2);

create table b (id number, d date);

insert into b values(1, null);
insert into b values(2, to_date('2014-01-01','yyyy-mm-dd'));
insert into b values(3, to_date('2013-01-01','yyyy-mm-dd'));
insert into b values(4, to_date('2013-01-01','yyyy-mm-dd'));

select aid id, case when adate = to_date('9999','yyyy') then null else rid end parent_id
from (
   select
     c.aid,
     c.rid,
     c.adate,
     nvl(b.d,to_date('9999','yyyy')) bdate 
   from (
         select a.id aid, a.rid rid, nvl(d,to_date('9999','yyyy')) adate 
         from a, b where a.id = b.id
         ) c, b 
          where c.rid = b.id
      ) where adate < bdate or adate = to_date('9999','yyyy')
order by id

此答案回答了后续问题,即仅获取属于特定根节点的记录:

select id, parent_id, level
from (
select aid id, case when adate = to_date('9999','yyyy') then null else rid end parent_id
from (select
   c.aid,
   c.rid,
   c.adate,
   nvl(b.d,to_date('9999','yyyy')) bdate from (select a.id aid, a.rid rid, nvl(d,to_date('9999','yyyy')) adate from a, b where a.id = b.id) c, b where c.rid = b.id
) where adate < bdate or adate = to_date('9999','yyyy')
) 
 START WITH id =1  -- ID of the ROOT node
connect by prior id = parent_id
order by id

1是否始终是唯一一个在null之前具有有效\u的节点?我认为可能存在这样的情况:1不是唯一一个在null之前具有有效\u的节点。但现在让它变得简单。是的,1是唯一可以将其有效_设置为null的节点。您好,我在原始问题的基础上又添加了一个问题。您介意回顾一下吗?您可以通过添加三个层次的遍历来完成。我还增加了一个水平指标。这要求您知道根节点id: