Reputation: 386
I am trying to use listagg but I'm getting the wrong output. Normally, I would use each case statement separately, but then how would I use listagg?
Table A:
JAN FEB MAR APR Tag
C 102
D T 100
D 101
C D B T 103
Table B:
Name Tag
Ally 100
Ben 101
Missy 102
Noah 103
Desired Output:
Ally Dog,Turtle
Ben Dog
Missy Chicken
Noah Chicken,Dog,Bird,Turtle
My attempted (wrong) code:
select listagg(
nvl(
case when a.jan = 'C' then 'Chicken'
when a.feb = 'D' then 'Dog'
when a.mar = 'B' then 'Bird'
when a.apr = 'T' then 'Turtle'
end,','),'none')
within group (order by a.tag)
from a where a.tag = b.tag
Upvotes: 1
Views: 394
Reputation: 91
with
-- sample data
taba (jan, feb, mar, apr, tag) as
(select 'c' , null, null, null, 102 from dual union all
select null, 'd' , null, 't' , 100 from dual union all
select null, 'd' , null, null, 101 from dual union all
select 'c' , 'd' , 'b' , 't' , 103 from dual
),
tabb (name, tag) as
(select 'ally' , 100 from dual union all
select 'ben' , 101 from dual union all
select 'missy', 102 from dual union all
select 'noah' , 103 from dual
),
tabab as (
--select a.tag, b.name, nvl(a.jan,'na') as jan, nvl(a.feb,'na') as feb, nvl(a.mar,'na') as mar, nvl(a.apr,'na') as apr
select
a.tag, b.name,
decode(a.jan,'b','bird','c','chicken','d','dog','t','turtle',null) as jan,
decode(a.feb,'b','bird','c','chicken','d','dog','t','turtle',null) as feb,
decode(a.mar,'b','bird','c','chicken','d','dog','t','turtle',null) as mar,
decode(a.apr,'b','bird','c','chicken','d','dog','t','turtle',null) as apr
from taba a
join tabb b
on a.tag = b.tag
)
select
name,
listagg(val,',') WITHIN GROUP (ORDER by decode(mon, 'JAN',1,'FEB',2,'MAR',3,'APR',4,null)) as listval
from tabab
unpivot
(
val
for mon in (jan,feb,mar,apr)
)
group by name
order by 1
;
Upvotes: 1
Reputation: 65218
You can construct the query through unpivoting within a subquery :
select b.Name, a.*
from b
join
(
select tag, listagg( case
when val = 'C' then
'Chicken'
when val = 'D' then
'Dog'
when val = 'B' then
'Bird'
when val = 'T' then
'Turtle'
end,',') within group (order by 1) as animals
from a
unpivot ( val for name in (jan as 'JAN', feb as 'FEB', mar as 'MAR', apr as 'APR') )
group by tag ) a
on b.tag = a.tag
order by a.tag
Upvotes: 2
Reputation: 142705
Here's one option, which uses multiple self-joins.
anima
CTE is here to simplify code; better have it in a table (even if it is a CTE) than use CASE
trim
+ regexp_replace
is used to remove superfluous commasHere you go:
SQL> with
2 -- sample data
3 taba (jan, feb, mar, apr, tag) as
4 (select 'c' , null, null, null, 102 from dual union all
5 select null, 'd' , null, 't' , 100 from dual union all
6 select null, 'd' , null, null, 101 from dual union all
7 select 'c' , 'd' , 'b' , 't' , 103 from dual
8 ),
9 tabb (name, tag) as
10 (select 'ally' , 100 from dual union all
11 select 'ben' , 101 from dual union all
12 select 'missy', 102 from dual union all
13 select 'noah' , 103 from dual
14 ),
15 --
16 -- replace animal codes with their names
17 anima (code, name) as
18 (select 'c', 'chicken' from dual union all
19 select 'd', 'dog' from dual union all
20 select 'b', 'bird' from dual union all
21 select 't', 'turtle' from dual
22 )
23 -- the final result
24 select b.name,
25 trim(',' from regexp_replace(n1.name ||','|| n2.name ||','|| n3.name ||','|| n4.name,
26 '( *, *){2,}', ','
27 )
28 ) result
29 from tabb b join taba a on a.tag = b.tag
30 left join anima n1 on n1.code = a.jan
31 left join anima n2 on n2.code = a.feb
32 left join anima n3 on n3.code = a.mar
33 left join anima n4 on n4.code = a.apr
34 order by b.name;
NAME RESULT
----- ------------------------------
ally dog,turtle
ben dog
missy chicken
noah chicken,dog,bird,turtle
SQL>
Upvotes: 1