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
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!