Home > Net >  Replacing comma separated integers in Oracle
Replacing comma separated integers in Oracle

Time:03-19

I have the following tables:

Employee:

Id NAME Qualification Experience(yrs)
1 Aaron Eng 2
2 Jacob CS 3
3 Jehan Art 1
4 Jenny Math 7

Task:

Task_Name Emp_id duration(mins) Wage
clean 1,3 200 50
wash 4 300 200
decor 1,2,4 250 300
errands 2,4 150 150

I would like to write an oracle query which returns the following output:

Task_responsbility:

Task_Name Employee duration(mins) Wage
clean Aaron,Jehan 200 50
wash Jenny 300 200
decor Aaron,Jacob,Jenny 250 300
errands Jacob,Jenny 150 150

I need the Emp_ids to be replaced by employee_names

Can someone please let me know how to go about this ?

CodePudding user response:

You can use a correlated sub-query:

SELECT task_name,
       ( SELECT LISTAGG(e.name, ',') WITHIN GROUP (
                  ORDER BY INSTR(',' || t.emp_id || ',', ',' || e.id || ',')
                )
         FROM   Employee e
         WHERE  INSTR(',' || t.emp_id || ',', ',' || e.id || ',') > 0
       ) AS emp_names,
       duration,
       wage
FROM   task t

Note: this will output the names in the same order as the id values in your list. If you want to order alphabetically then you can use ORDER BY e.name,

Which, for the sample data:

CREATE TABLE Employee(Id, NAME, Qualification, Experience) AS
SELECT 1, 'Aaron', 'Eng',  2 FROM DUAL UNION ALL
SELECT 2, 'Jacob', 'CS',   3 FROM DUAL UNION ALL
SELECT 3, 'Jehan', 'Art',  1 FROM DUAL UNION ALL
SELECT 4, 'Jenny', 'Math', 7 FROM DUAL;

CREATE TABLE Task (Task_Name, Emp_id, duration, Wage) AS
SELECT 'clean',   '1,3',   200,  50 FROM DUAL UNION ALL
SELECT 'wash',    '4',     300, 200 FROM DUAL UNION ALL
SELECT 'decor',   '1,2,4', 250, 300 FROM DUAL UNION ALL
SELECT 'errands', '2,4',   150, 150 FROM DUAL;

Which outputs:

TASK_NAME EMP_NAMES DURATION WAGE
clean Aaron,Jehan 200 50
wash Jenny 300 200
decor Aaron,Jacob,Jenny 250 300
errands Jacob,Jenny 150 150

db<>fiddle here

CodePudding user response:

You should not store your id s(int) in "emp_id"(presumably varchar(x)) column. Check out: How to store a list in a column of a database table

You should store each emp_id in another row in your task table to comply first normal form.

create table emp(
id number(10),
name varchar(30),
Qualification varchar(30),
Experience number(10));

create table task(
Task_Name varchar(30),
id number(10),
duration number(10),
wage number(10));

INSERT ALL
   INTO emp VALUES (1,'Aaron','Eng', 2 )
   INTO emp VALUES (2,'Jacob','CS',  3 )
   INTO emp VALUES (3,'Jehan','Art', 1 )
   INTO emp VALUES (4,'Jenny','Math', 7 )
SELECT 1 FROM DUAL;

INSERT ALL
INTO task VALUES('clean', 1, 200, 50 )
INTO task VALUES('clean', 3, 200, 50 )
INTO task VALUES('wash', 4, 300, 200)
INTO task VALUES('decor', 1, 250, 300)
INTO task VALUES('decor', 2, 250, 300)
INTO task VALUES('decor', 4, 250, 300)
INTO task VALUES('errands', 2, 150, 150)
INTO task VALUES('errands', 4, 150, 150)
SELECT 1 FROM DUAL;

After this point joining tables are easy and no need complex functions:

with tab1 as (select * from emp e join task t
on e.id=t.id)
select task_name,
 LISTAGG(e.name, ',') WITHIN GROUP (
                  ORDER BY e.name) name_list, max(duration) duration, max(wage) wage from tab1 e group by task_name;

DB Fiddle:

  • Related