Reputation: 449
I have a 'MASTER' table as shown below:
Entity Cat1 Cat2
A Mary;Steve Jacob
B Alex;John Sally;Andrew
Another table 'PERSON' has associations of person's name (this could be InfoID as well) with emails.
Name Email InfoID
Mary [email protected] mryD
Steve [email protected] stvR
Jacob [email protected] jacbb
Sally [email protected] sallD
Alex [email protected] alexT
John [email protected] johP
Andrew [email protected] andV
I want to join the person table with master such as:
Entity Cat1 EmailCat1 Cat2 EmailCat2
A Mary;Steve [email protected];[email protected] Jacob [email protected]
B Alex;John [email protected];[email protected] Sally;Andrew [email protected];[email protected]
any insights on how to go about it?
Upvotes: 0
Views: 46
Reputation: 1555
Honestly, your master table design needs to be normalized. But, in the meantime you could try this query below :
with
needed_rows_for_cat1_tab (lvl) as (
select level from dual
connect by level <= (select max(regexp_count(Cat1, ';')) from Your_bad_master_tab) + 1
)
, needed_rows_for_cat2_tab (lvl) as (
select level from dual
connect by level <= (select max(regexp_count(Cat2, ';')) from Your_bad_master_tab) + 1
)
, split_cat1_val_tab as (
select Entity, Cat1
, substr(Cat1||';'
, lag(pos, 1, 0)over(partition by Entity order by lvl) + 1
, pos - lag(pos, 1, 0)over(partition by Entity order by lvl) - 1
) val
, lvl
, pos
, 1 cat
from (
select Entity, Cat1, instr(Cat1||';', ';', 1, r1.lvl)pos, r1.lvl
from Your_bad_master_tab c1
join needed_rows_for_cat1_tab r1 on r1.lvl <= regexp_count(Cat1, ';') + 1
)
)
, split_cat2_val_tab as (
select Entity, Cat2
, substr(Cat2||';'
, lag(pos, 1, 0)over(partition by Entity order by lvl) + 1
, pos - lag(pos, 1, 0)over(partition by Entity order by lvl) - 1
) val
, lvl
, pos
, 2 cat
from (
select Entity, Cat2, instr(Cat2||';', ';', 1, r2.lvl)pos, r2.lvl
from Your_bad_master_tab c1
join needed_rows_for_cat2_tab r2 on r2.lvl <= regexp_count(Cat2, ';') + 1
)
)
select ENTITY
, max(decode(cat, 1, CAT1, null)) CAT1
, listagg(decode(cat, 1, EMAIL, null), ';')within group (order by lvl) EmailCat1
, max(decode(cat, 2, CAT1, null)) CAT2
, listagg(decode(cat, 2, EMAIL, null), ';')within group (order by lvl) EmailCat2
from (
select c.*, p.Email
from split_cat1_val_tab c join Your_person_tab p on (c.val = p.name)
union all
select c.*, p.Email
from split_cat2_val_tab c join Your_person_tab p on (c.val = p.name)
)
group by ENTITY
;
Here are your sample data
--drop table Your_bad_master_tab purge;
create table Your_bad_master_tab (Entity, Cat1, Cat2) as
select 'A', 'Mary;Steve', 'Jacob' from dual union all
select 'B', 'Alex;John', 'Sally;Andrew' from dual
;
--drop table Your_person_tab purge;
create table Your_person_tab (Name, Email, InfoID) as
select 'Mary', '[email protected]' ,'mryD' from dual union all
select 'Steve', '[email protected]' ,'stvR' from dual union all
select 'Jacob', '[email protected]' ,'jacbb' from dual union all
select 'Sally', '[email protected]' ,'sallD' from dual union all
select 'Alex', '[email protected]' ,'alexT' from dual union all
select 'John', '[email protected]' ,'johP' from dual union all
select 'Andrew', '[email protected]' ,'andV' from dual
;
Upvotes: 1