SQL> create table emp ( eid int, en varchar2(10), d varchar2(20));
Table created.
SQL> insert into emp values (1,'Tom','1,2');
1 row created.
SQL> insert into emp values (2,'Mike','2,3');
1 row created.
SQL> insert into emp values (3,'Sue','3');
1 row created.
SQL>
SQL> create table dept ( did int, dn varchar2(20));
Table created.
SQL>
SQL> insert into dept values (1,'Sales');
1 row created.
SQL> insert into dept values (2,'HR');
1 row created.
SQL> insert into dept values (3,'Testing');
1 row created.
SQL> insert into dept values (4,'Admin');
1 row created.
SQL>
SQL> select eid,en,
2
SQL>
SQL>
--
-- first we'll convert the list to rows
--
SQL>
SQL> with dept_as_rows as
2 (
3 select eid,en,
4 substr( ','||d||',' ,
5 instr( ','||d||',' , ',' ,1,r)+1 ,
6 instr( ','||d||',' , ',' ,1,r+1) -
7 instr( ','||d||',' , ',' ,1,r) -1) txt
8 from emp ,
9 ( select level r
10 from dual
11 connect by level <= ( select max(did) from dept )
12 )
13 where r <= length(d) - length(replace(d,',')) + 1
14 )
15 select *
16 from dept_as_rows
17 order by 1,2
18 /
EID EN TXT
---------- ---------- ----------------------------------------------------------------------------------------
1 Tom 1
1 Tom 2
2 Mike 2
2 Mike 3
3 Sue 3
5 rows selected.
--
-- now we can join back to dept to get the names
--
SQL>
SQL> with dept_as_rows as
2 (
3 select eid,en,
4 to_number(substr( ','||d||',' ,
5 instr( ','||d||',' , ',' ,1,r)+1 ,
6 instr( ','||d||',' , ',' ,1,r+1) -
7 instr( ','||d||',' , ',' ,1,r) -1)) txt
8 from emp ,
9 ( select level r
10 from dual
11 connect by level <= ( select max(did) from dept )
12 )
13 where r <= length(d) - length(replace(d,',')) + 1
14 )
15 select *
16 from dept_as_rows dr,
17 dept d
18 where dr.txt = d.did
19 order by 1,2
20 /
EID EN TXT DID DN
---------- ---------- ---------- ---------- --------------------
1 Tom 1 1 Sales
1 Tom 2 2 HR
2 Mike 3 3 Testing
2 Mike 2 2 HR
3 Sue 3 3 Testing
5 rows selected.
--
-- now we can concatenate using LISTAGG
--
SQL>
SQL>
SQL> with dept_as_rows as
2 (
3 select eid,en,
4 to_number(substr( ','||d||',' ,
5 instr( ','||d||',' , ',' ,1,r)+1 ,
6 instr( ','||d||',' , ',' ,1,r+1) -
7 instr( ','||d||',' , ',' ,1,r) -1)) txt
8 from emp ,
9 ( select level r
10 from dual
11 connect by level <= ( select max(did) from dept )
12 )
13 where r <= length(d) - length(replace(d,',')) + 1
14 )
15 select dr.eid, dr.en, listagg(d.dn,',') within group ( order by d.did ) as depts
16 from dept_as_rows dr,
17 dept d
18 where dr.txt = d.did
19 group by dr.eid, dr.en
20 order by 1,2
21 /
EID EN DEPTS
---------- ---------- ------------------------------
1 Tom Sales,HR
2 Mike HR,Testing
3 Sue Testing
3 rows selected.
SQL>
SQL>
SQL>