Oracle SQL中的分层数据

时间:2019-02-27 14:50:18

标签: sql oracle group-by

我在Oracle SQL中有这样的tbl_parent,示例数据如下:

 Id(primary key)   parentid   childid

  1                 1           2
  2                 1           3
  3                 2           1
  4                 3           1  -- This row is wrong

在上表中,错误地插入了一些行,例如,如果parent_id 1具有child_id 3,则parent_id 3不应具有child_id 1,因为3已经存在1的孩子,所以不能成为父母,我有5000多个行,想找到这些不正确的行,请帮忙吗?

2 个答案:

答案 0 :(得分:1)

greatestleast函数可以用作

select least(parentid,childid) as least_par_chi_id,
       greatest(parentid,childid) as greatest_par_chi_id
  from tab
 group by greatest(parentid,childid), least(parentid,childid)
having count(*)>1;

答案 1 :(得分:0)

基本上,您正在表中寻找周期

Oracle识别层次查询中周期的功能是

CONNECT BY NOCYCLE and CONNECT_BY_ISCYCLE

此查询显示所有导致循环的节点-is_Cycle = 1

select tbl.* ,
CONNECT_BY_ISCYCLE  is_Cycle, 
SYS_CONNECT_BY_PATH(childid, '/') path
from tbl
CONNECT BY NOCYCLE PRIOR childid = parentid

对于您的数据,结果是

  PARENTID    CHILDID   IS_CYCLE PATH     
---------- ---------- ---------- ----------
         1          2          0 /2         
         2          1          1 /2/1       
         1          3          1 /2/1/3     
         1          3          0 /3         
         3          1          1 /3/1       
         1          2          1 /3/1/2     
         2          1          0 /1         
         1          2          1 /1/2       
         1          3          1 /1/3       
         3          1          0 /1         
         1          2          1 /1/2       
         1          3          1 /1/3 

请注意,每个循环在几个地方都可以识别,因此您可以获得一些冗余数据。

此方法的优点是,它也可以工作更长的周期(简单的GROUP BY方法失败了)。

长度为3的循环的示例:

create table tbl as
select 1 parentid, 2   childid from dual union all
select 2 parentid, 3   childid from dual union all
select 3 parentid, 1   childid from dual;

  PARENTID    CHILDID   IS_CYCLE PATH     
---------- ---------- ---------- ----------
         1          2          0 /2         
         2          3          0 /2/3       
         3          1          1 /2/3/1     
         2          3          0 /3         
         3          1          0 /3/1       
         1          2          1 /3/1/2     
         3          1          0 /1         
         1          2          0 /1/2       
         2          3          1 /1/2/3