Reputation: 145
I want to get group of column values with comma separated including Null values of Group by columns. Group by treats NUll values as separate group.
Let us say there is an input_table:
+----------------------------------------------------+
| obj1 obj2 obj3 fail_msg |
+----------------------------------------------------+
| |
| A msg1 |
| A B C msg2 |
| A B D msg3 |
+----------------------------------------------------+
i want to get the results as below from input table.
Results:
----------------------------------
A B C msg1, msg2
A B D msg1, msg3
Similar to Listagg function , but group by with Null values.
Example:
select LISTAGG(fail_msg, ', ') WITHIN GROUP(ORDER BY fail_msg) failure_ message
from input_table group by obj1, obj2, obj3
But this query is not merging null values in listagg()
can anyone please help me?
Thanks in advance.
Upvotes: 0
Views: 3949
Reputation: 45659
GROUP BY
alone won't yield this result no matter what you do, because it assigns each row to one and only one group. (There are ways to get summary rows, or multiple grouping sets in one query, but still those don't help here...)
The odds are you can do this more easily outside of SQL; but if you must do it in a query then you could try an approach like the following.
Note that this query is good enough for the example you gave; if your real requirements are more complicated, you may have to expand on these basic ideas. Also note that I'm showing the logic incrementally for clear explanation, but just the last query is what you'd want:
So first we can get a list of the messages with NULL values.
select *
from input_table
where obj2 is NULL
and obj3 is NULL
We need to join this with the list of obj2
and obj3
values that exist for the given obj1
value; this is to create individual message records to apply in each group.
select null_list.obj1, obj_list.obj2, obj_list.obj3, null_list.fail_msg
from input_table null_list
inner join (select distinct obj1, obj2, obj3
from input_table) as obj_list
on null_list.obj1 = obj_list.obj1
Now combine that with the list of messages that didn't have null values
select null_list.obj1, obj_list.obj2, obj_list.obj3, null_list.fail_msg
from input_table null_list
inner join (select distinct obj1, obj2, obj3
from input_table) as obj_list
on null_list.obj1 = obj_list.obj1
UNION ALL
select *
from input_table
where obj2 is not null
and obj3 is not null
(Note that the above only handles records where obj2 and obj3 either both are null, or neither are null. This is part of where I'm only addressing the example and you'd need to add more logic if you need to deal with different combinations of columns being null. That can get messy fast; like I said, SQL isn't really the tool for this job.)
Well now you have it as a list of messages applied to specific combinations of obj1,obj2,obj3 and a simple LILSTAGG should get you the rest of the way there.
Upvotes: 0
Reputation: 4818
That's very bad code but seem to do what you need:
with d as (
select 'A' as o1, 'B' as o2, 'C' as o3, 'm1' as m from dual union all
select 'A' as o1, 'B' as o2, 'D' as o3, 'm3' as m from dual union all
select 'A' as o1, null as o2, null as o3, 'm2' as m from dual
)
select o1, o2, o3, listagg(m, ',') within group (order by o1) from
(select distinct nvl(d1.o1, d2.o1) as o1, nvl(d1.o2, d2.o2) as o2, nvl(d1.o3, d2.o3) as o3, d1.m
from d d1 inner join d d2 on (nvl(d1.o1,d2.o1) = nvl(d2.o1, d1.o1) and nvl(d1.o2,d2.o2) = nvl(d2.o2, d1.o2) and nvl(d1.o3,d2.o3) = nvl(d2.o3, d1.o3)))
group by o1, o2, o3;
Upvotes: 1