To do that join a table with integers, so that every employee row occurs as often as there are department IDs in its string but at least one time. For the rows in the join result the numbers i go from 1 to n, where n is the number of IDs in the string for that employee (if there are any department IDs for the employee). Then you can use REGEXP_SUBSTR()
to get the _i_th number from the string. Use that to left join the departments, to get the department name. Then use an aggregation using LISTAGG()
to get a single row for each employee again.
SELECT E.EMPID,
E.NAME,
E.DEPTID,
LISTAGG(D.DEPTNAME, ',') WITHIN GROUP (ORDER BY I.I) DEPTNAME
FROM EMPLOYEE E
LEFT JOIN (SELECT ROW_NUMBER() OVER (ORDER BY DEPTID) I
FROM DEPARTMENT) I
ON I.I <= REGEXP_COUNT(E.DEPTID, ',') + 1
LEFT JOIN DEPARTMENT D
ON D.DEPTID = TO_NUMBER(REPLACE(REGEXP_SUBSTR(',' || E.DEPTID, ',([[:digit:]]+)', 1, I.I), ',', ''))
GROUP BY E.EMPID,
E.NAME,
E.DEPTID;
db<>fiddle