Reputation: 13
Table Organization(organizationId, parentId, name) Table Setting(id, organizationId, settingName, settingValue)
Here in |a,1| : a is settingName, 1 is settingValue
Organization A |a,1| |b,2| |c,3| |d,4|
Organization B |b,5|
Organization C |a,8|
Organization D |c,2|
A->B->C->D (hierarchy) Now get query of organization D should give me (a,8)(b,5)(c,2)(d,4)
My query :
with recursive cte as (
select
*, 1 as level
from
Organization
where
organizationId = 3
union ALL
select
t.*, cte.level+1
from
cte
join Organization t on
t.OrganizationId = cte.parentId )
-- select
-- ss.OrganizationId,ss.parentId, ss.settingName,ss.settingValue
-- from
select
cte.OrganizationId,
cte.ParentId,
s.settingName ,
s.settingValue,
level
from
cte
inner join Settings s on
s.organizationId = cte.OrganizationId
-- as ss group by ss.settingName
This gives me settings from all the organizations but i need the values of most recent child(if there is any) else from the parent (This should continue till the ROOT organization, bottom to up approach)
Upvotes: 1
Views: 590
Reputation: 1
Create schema
create table t42 (id number, parent_id number, flag varchar2(1), str
varchar2(20));
insert into t42 values (1, null, 'A', 'Parent');
insert into t42 values (2, 1, 'B', 'Child 1'); insert into t42
values (3, 1, 'C', 'Child 2'); insert into t42 values (4, 1, 'C',
'Child 3');
insert into t42 values (5, 2, 'D', 'Grandchild 1 1'); insert into
t42 values (6, 3, 'B', 'Grandchild 2 1'); insert into t42 values (7,
3, 'D', 'Grandchild 2 2');
now excecute below query
select t.id, t.parent_id, t.flag, t.str
from (
select t.*, dense_rank() over (partition by flag order by lvl) as rn
from (
select t.*, level as lvl
from t42 t
start with parent_id is null
connect by prior id = parent_id
) t
) t
where rn = 1
and flag = 'A';
select t.id, t.parent_id, t.flag, t.str
from (
select t.*, dense_rank() over (partition by flag order by lvl) as rn
from (
select t.*, level as lvl
from t42 t
start with parent_id is null
connect by prior id = parent_id
) t
) t
where rn = 1
and flag = 'B';
select t.id, t.parent_id, t.flag, t.str
from (
select t.*, dense_rank() over (partition by flag order by lvl) as rn
from (
select t.*, level as lvl
from t42 t
start with parent_id is null
connect by prior id = parent_id
) t
) t
where rn = 1
and flag = 'C';
select t.id, t.parent_id, t.flag, t.str
from (
select t.*, dense_rank() over (partition by flag order by lvl) as rn
from (
select t.*, level as lvl
from t42 t
start with parent_id is null
connect by prior id = parent_id
) t
) t
where rn = 1
and flag = 'D';
Upvotes: 0
Reputation: 22811
Keep track of orgId of interest and level of the setting. Find first value by level
with recursive cte as (
select s.*, 1 as level, s.organizationId as orgId
from Settings s
where s.organizationId = 4
union ALL
select s.*, cte.level+1, cte.orgId
from cte
join Organization t on t.organizationId = cte.organizationId
join settings s on s.organizationId = t.ParentId
)
select distinct orgid, settingname, first_value(settingvalue) over(partition by orgId, settingname order by level)
from cte
EDIT Case when an organization can have no settings
with recursive cte as (
select t.organizationId, s.settingname, s.settingvalue, 1 as level, t.organizationId orgId
from Organization t
left join Settings s on t.organizationId = s.organizationId
where t.organizationId = 5
union ALL
select t.ParentId, s.settingname, s.settingvalue, cte.level+1, cte.orgId
from cte
join Organization t on t.organizationId = cte.organizationId
left join settings s on s.organizationId = t.ParentId
)
select distinct orgid, settingname, first_value(settingvalue) over(partition by orgId, settingname order by level)
from cte
where settingName is not null
order by orgid, settingname;
Upvotes: 1