Sql 在oracle中查找根父级的递归查询

Sql 在oracle中查找根父级的递归查询,sql,recursion,Sql,Recursion,我试图在一个具有分层数据的表中找出根父级。下面的示例按预期工作,但我需要做一些额外的事情。我希望避免查询忽略null id1,并在根父项为null时显示(根父项-1) with table_a ( id1, child_id ) as ( select null, 1 from dual union all select 1, 2 from dual union all select 2, 3 from dual union all

我试图在一个具有分层数据的表中找出根父级。下面的示例按预期工作,但我需要做一些额外的事情。我希望避免查询忽略null id1,并在根父项为null时显示(根父项-1)

with table_a ( id1, child_id ) as (
        select null, 1    from dual union all
       select 1, 2    from dual union all
       select 2, 3    from dual union all
       select 3, NULL from dual union all
       select 4, NULL from dual union all
       select 5, 6    from dual union all
       select 6, 7    from dual union all
       select 7, 8    from dual union all
       select 8, NULL from dual
     )
select     connect_by_root id1 as id, id1 as root_parent_id
from       table_a
where      connect_by_isleaf = 1
connect by child_id = prior id1

order by id 1

This brings up the following data
4   4
6   5
7   5
8   5
5   5
3   null
null    null    
2   null
1   null

what I want is 

3   1
1   1
2   1
4   4
7   5
8   5
5   5
6   5

is it possible?

Thanks for the help

这看起来是可行的,但可能是不正确的,因为我不太理解选择1的逻辑,在我看来是任意的,与实际数据不太一样。 正如Hogan已经提出的,如果您可以提供一个解释或扩展的数据集来测试这个层次结构,这将是很有帮助的

with table_a ( id1, child_id ) as (
       select null, 1    from dual union all
       select 1,    2    from dual union all
       select 2,    3    from dual union all
       select 3,    NULL from dual union all
       select 4,    NULL from dual union all
       select 5,    6    from dual union all
       select 6,    7    from dual union all
       select 7,    8    from dual union all
       select 8,    NULL from dual
     )
select     connect_by_root id1 as id, id1 as root_parent_id
from       table_a
where      connect_by_isleaf = 1 and connect_by_root id1 is not null
connect by nocycle child_id = prior nvl(id1, 1)
order by 2, 1;
示例执行:

FSITJA@dbd01 2019-07-19 13:51:13> with table_a ( id1, child_id ) as (
  2         select null, 1    from dual union all
  3         select 1,    2    from dual union all
  4         select 2,    3    from dual union all
  5         select 3,    NULL from dual union all
  6         select 4,    NULL from dual union all
  7         select 5,    6    from dual union all
  8         select 6,    7    from dual union all
  9         select 7,    8    from dual union all
 10         select 8,    NULL from dual
 11       )
 12  select     connect_by_root id1 as id, id1 as root_parent_id
 13  from       table_a
 14  where      connect_by_isleaf = 1 and connect_by_root id1 is not null
 15  connect by nocycle child_id = prior nvl(id1, 1)
 16  order by 2, 1;

        ID ROOT_PARENT_ID
---------- --------------
         1              1
         2              1
         3              1
         4              4
         5              5
         6              5
         7              5
         8              5

8 rows selected.

这看起来是可行的,但可能是不正确的,因为我不太理解选择1的逻辑,在我看来是任意的,与实际数据不太一样。 正如Hogan已经提出的,如果您可以提供一个解释或扩展的数据集来测试这个层次结构,这将是很有帮助的

with table_a ( id1, child_id ) as (
       select null, 1    from dual union all
       select 1,    2    from dual union all
       select 2,    3    from dual union all
       select 3,    NULL from dual union all
       select 4,    NULL from dual union all
       select 5,    6    from dual union all
       select 6,    7    from dual union all
       select 7,    8    from dual union all
       select 8,    NULL from dual
     )
select     connect_by_root id1 as id, id1 as root_parent_id
from       table_a
where      connect_by_isleaf = 1 and connect_by_root id1 is not null
connect by nocycle child_id = prior nvl(id1, 1)
order by 2, 1;
示例执行:

FSITJA@dbd01 2019-07-19 13:51:13> with table_a ( id1, child_id ) as (
  2         select null, 1    from dual union all
  3         select 1,    2    from dual union all
  4         select 2,    3    from dual union all
  5         select 3,    NULL from dual union all
  6         select 4,    NULL from dual union all
  7         select 5,    6    from dual union all
  8         select 6,    7    from dual union all
  9         select 7,    8    from dual union all
 10         select 8,    NULL from dual
 11       )
 12  select     connect_by_root id1 as id, id1 as root_parent_id
 13  from       table_a
 14  where      connect_by_isleaf = 1 and connect_by_root id1 is not null
 15  connect by nocycle child_id = prior nvl(id1, 1)
 16  order by 2, 1;

        ID ROOT_PARENT_ID
---------- --------------
         1              1
         2              1
         3              1
         4              4
         5              5
         6              5
         7              5
         8              5

8 rows selected.

使用递归CTE,您可以执行以下操作:

with table_a ( id1, child_id ) as (
        select null, 1    from dual union all
       select 1, 2    from dual union all
       select 2, 3    from dual union all
       select 3, NULL from dual union all
       select 4, NULL from dual union all
       select 5, 6    from dual union all
       select 6, 7    from dual union all
       select 7, 8    from dual union all
       select 8, NULL from dual
),
n (s, e) as (
  select id1 as s, child_id as e from table_a where id1 not in 
    (select child_id from table_a 
     where id1 is not null and child_id is not null)
  union all
  select n.s, a.child_id
  from n
  join table_a a on a.id1 = n.e
)
select
  coalesce(e, s) as c, s
from n
order by s
结果:

 C S 
 - - 
 3 1 
 1 1 
 2 1 
 4 4 
 5 5 
 7 5 
 8 5 
 6 5 

作为旁注,“递归CTE”比旧式的
connectby

更灵活。使用递归CTE,您可以执行以下操作:

with table_a ( id1, child_id ) as (
        select null, 1    from dual union all
       select 1, 2    from dual union all
       select 2, 3    from dual union all
       select 3, NULL from dual union all
       select 4, NULL from dual union all
       select 5, 6    from dual union all
       select 6, 7    from dual union all
       select 7, 8    from dual union all
       select 8, NULL from dual
),
n (s, e) as (
  select id1 as s, child_id as e from table_a where id1 not in 
    (select child_id from table_a 
     where id1 is not null and child_id is not null)
  union all
  select n.s, a.child_id
  from n
  join table_a a on a.id1 = n.e
)
select
  coalesce(e, s) as c, s
from n
order by s
结果:

 C S 
 - - 
 3 1 
 1 1 
 2 1 
 4 4 
 5 5 
 7 5 
 8 5 
 6 5 

作为旁注,“递归CTE”比旧式的
connectby

更灵活,它如何确切地知道为空列输入1?确实如此。使用递归CTE。它如何确切地知道为null列输入1?确实如此。使用递归CTE。