Skip to Main Content
  • Questions
  • using connect by without relationship using parent_id

Breadcrumb

Question and Answer

Connor McDonald

Thanks for the question, Talal.

Asked: November 06, 2017 - 7:15 pm UTC

Last updated: November 09, 2017 - 1:26 am UTC

Version: oracle 11g R2

Viewed 1000+ times

You Asked

Hi,
I have information about father's , mother's and children but there is no relationship between the rows using Paernt_id
as follows,

drop table tbl_family;

create table tbl_family
(
father nvarchar2(50) ,
mother nvarchar2(50) ,
child nvarchar2(50) ,
birth date null
);

insert into tbl_family (father,mother,child,birth) values ('Ralf', 'Nina', 'Adam', to_date( '17-02-1989' , 'dd-MM-yyyy') );
insert into tbl_family (father,mother,child,birth) values ('Ralf', 'Nina', 'Emma', null) ;
insert into tbl_family (father,mother,child,birth) values ('Ralf', 'Birgit', 'Andi', to_date( '09-06-1982' , 'dd-MM-yyyy') );
insert into tbl_family (father,mother,child,birth) values ('Alec', 'Birgit', 'Amos', to_date( '18-05-1977',  'dd-MM-yyyy')) ;
insert into tbl_family (father,mother,child,birth) values ('Aaron', 'Nanci', 'Alfred', to_date( '28-10-1934',  'dd-MM-yyyy') );
insert into tbl_family (father,mother,child,birth) values ('Aaron', 'Rike', 'Ashley', null) ;
insert into tbl_family (father,mother,child,birth) values ('Andy', 'Celine', 'Roland', to_date( '20-12-1952',  'dd-MM-yyyy') );



I want to display all brothers/sisters (either same father or mother)

the output will be like :

Adam/Emma/Andi 
Andi/Amos
Alfred/Ashley


is there any way to use "start with .. connect by" ?

Many thanks
Talal

and Chris said...

I'm not sure why you want to use connect by? You've only got one level in the hierarchy!

It seems like listagg is more what you need. You can use grouping sets to get the list of children for each mother and father in one go:

select coalesce ( mother, father ) par, 
       listagg(child, ',') within group (order by child) sibs
from   tbl_family
group  by grouping sets ( (mother), (father) )
having count(*) > 1;

PAR      SIBS                         
Birgit   Amos,Andi
Nina     Adam,Emma
Aaron    Alfred,Ashley
Ralf     Adam,Andi,Emma


But this includes children for one parent which a are subset of another's (Nina and Ralf's kids).

If you want to avoid this, you need to exclude children who have more siblings from one parent than the other.

One way to do this to:

- Use the collect function to load the children into an array
- Use submultiset to exclude siblings that are a subset of another

Sadly, collect doesn't support grouping sets yet (run on 12.2.0.1):

create or replace type arr is table of varchar2(50);
/

select mother, father, 
       cast ( collect ( cast ( child as varchar2(50) ) ) as arr ) c,
       listagg(child, ',') within group (order by child) 
from   tbl_family
group  by grouping sets ( mother , father );

SQL Error: ORA-03001: unimplemented feature


You can workaround this by collecting the mothers and fathers separately. Then unioning them back together.

You then return those siblings that aren't a submultiset of another:

with fathers as ( 
  select father par, 
         cast ( collect ( cast ( child as varchar2(50) ) ) as arr ) c,
         listagg(child, ',') within group (order by child) sibs
  from   tbl_family
  group  by father
  having count(*) > 1
), mothers as ( 
  select mother par, 
         cast ( collect ( cast ( child as varchar2(50) ) ) as arr ) c,
         listagg(child, ',') within group (order by child) sibs
  from   tbl_family
  group  by mother
  having count(*) > 1
), children as (
  select * from fathers
  union all 
  select * from mothers
)
  select distinct sibs from children c
  where  not exists (
    select * from children subc
    where  c.c submultiset of subc.c 
    and    c.sibs <> subc.sibs
  );

SIBS                         
Alfred,Ashley
Adam,Andi,Emma
Amos,Andi


Obviously, as you're working with given names it's easy to have siblings that are a subset of an unrelated group of siblings... Even when you throw in their family names and their parent's you can end up with spurious subsets. Beware!

Rating

  (1 rating)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Talal Hallaj, November 08, 2017 - 7:43 pm UTC

Thanks much for the ideas.
Very informative
Connor McDonald
November 09, 2017 - 1:26 am UTC

glad we could help

More to Explore

SQL

The Oracle documentation contains a complete SQL reference.