Этот запрос также объединяет дочерние элементы:
with mcnt (id, parent_id, name, continent, child_members, own_members, ff,level_members) as (
select
p.id, p.parent_id, p.name, p.continent
, 0 as child_members
, (select count(*) from member m where m.place_id=p.id) as own_members
, row_number()over(partition by p.parent_id order by p.id) ff
, sum((select count(*) from member m where m.place_id=p.id))over(partition by p.parent_id) level_members
from place p
where not exists(select null from place child where p.id = child.parent_id)
union all
select p.id, p.parent_id, p.name, p.continent
, mcnt.level_members + mcnt.child_members as child_members
, (select count(*) from member m where m.place_id=p.id) as own_members
, row_number()over(partition by p.parent_id order by p.id) ff
, sum((select count(*) from member m where m.place_id=p.id))over(partition by p.parent_id) level_members
from mcnt, place p
where mcnt.parent_id=p.id
and mcnt.ff=1
)
select
id, parent_id, name, continent, child_members, own_members
,child_members+own_members as total_cnt
from mcnt
order by id;
Полный пример:
with
-- sample data
place (id, parent_id, name, continent) as
(select 11, null, 'USA' , 'America' from dual union all
select 22, 11 , 'New York' , 'America' from dual union all
select 33, 22 , 'Manhattan', 'America' from dual union all
--
select 35, 33 , 'Central Park', 'America' from dual union all
select 44, null, 'Brasil' , 'America' from dual union all
select 55, 44 , 'Rio' , 'America' from dual union all
select 66, null, 'France' , 'Europe' from dual union all
select 77, 66 , 'Paris' , 'Europe' from dual union all
select 88, 66 , 'Nice' , 'Europe' from dual
),
member (id, place_id) as
(select 1, 22 from dual union all
select 2, 77 from dual union all
select 3, 33 from dual union all
select 4, 22 from dual union all
select 5, 55 from dual union all
select 6, 55 from dual union all
select 7, 88 from dual union all
select 8, 88 from dual union all
select 9, 88 from dual union all
select 10, 22 from dual
--
union all select 1001, 35 from dual
union all select 1002, 35 from dual
union all select 1003, 35 from dual
),
mcnt (id, parent_id, name, continent, child_members, own_members, ff,level_members) as (
select
p.id, p.parent_id, p.name, p.continent
, 0 as child_members
, (select count(*) from member m where m.place_id=p.id) as own_members
, row_number()over(partition by p.parent_id order by p.id) ff
, sum((select count(*) from member m where m.place_id=p.id))over(partition by p.parent_id) level_members
from place p
where not exists(select null from place child where p.id = child.parent_id)
union all
select p.id, p.parent_id, p.name, p.continent
, mcnt.level_members + mcnt.child_members as child_members
, (select count(*) from member m where m.place_id=p.id) as own_members
, row_number()over(partition by p.parent_id order by p.id) ff
, sum((select count(*) from member m where m.place_id=p.id))over(partition by p.parent_id) level_members
from mcnt, place p
where mcnt.parent_id=p.id
and mcnt.ff=1
)
select
id, parent_id, name, continent, child_members, own_members
,child_members+own_members as total_cnt
from mcnt
order by id;
Результаты:
ID PARENT_ID NAME CONTINE CHILD_MEMBERS OWN_MEMBERS TOTAL_CNT
---------- ---------- ------------ ------- ------------- ----------- ----------
11 USA America 7 0 7
22 11 New York America 4 3 7
33 22 Manhattan America 3 1 4
35 33 Central Park America 0 3 3
44 Brasil America 2 0 2
55 44 Rio America 0 2 2
66 France Europe 4 0 4
77 66 Paris Europe 0 1 1
88 66 Nice Europe 0 3 3
9 rows selected.