I have following example:
create table products (name text, id integer, type smallint, category integer);
insert into products values
('apple', 23, 1, 1200),
('apple', 23, 1, 999),
('apple', 31, 2, 1200),
('apple', 23, 3, 1200),
('orange', 10, 1, 200),
('orange', 10, 2, 200),
('orange', 10, 2, 230),
('orange', 10, 3, 200),
('orange', 64, 1, 700),
('orange', 70, 2, 700);
I want the results to be like this:
name | type_1_3_id | type_2_id |
---|---|---|
apple | 23 | 31 |
orange | {10,64} | {10,70} |
But postgres forces me to group by column type, which makes my results not as I want them to be
select distinct name,
case when type in (1,3) then array_agg(distinct id) end as type_1_3,
case when type = 2 then array_agg(distinct id) end as type_2
from products
group by 1, type
order by 1
2
Answers
Since you want
DISTINCT
values and also you want to exclude nulls, you can’t useARRAY_AGG()
out of the box. You can filter and aggregate separately and then join these aggregations.For example:
Result:
See running example at db<>fiddle.
Use the
filter
clause with yourarray_agg
function:With conditional aggregation
array_agg(case when... then ... end)
a null value is returned for the unmatched rows, while filters would aggregate only the specified rows within the where clause.Demo