how to exclude null values in array_agg like in string_agg using postgres?
With postgresql-9.3 one can do this;
SELECT g.id,
array_remove(array_agg(CASE WHEN g.canonical = 'Y' THEN g.users ELSE NULL END), NULL) canonical_users,
array_remove(array_agg(CASE WHEN g.canonical = 'N' THEN g.users ELSE NULL END), NULL) non_canonical_users
FROM groups g
GROUP BY g.id;
Update: with postgresql-9.4;
SELECT g.id,
array_agg(g.users) FILTER (WHERE g.canonical = 'Y') canonical_users,
array_agg(g.users) FILTER (WHERE g.canonical = 'N') non_canonical_users
FROM groups g
GROUP BY g.id;
Update (2022-02-19): also with postgresql-9.4;
This results in an empty array when all values in an array are null instead of returning null;
SELECT g.id,
coalesce( array_agg(g.users) FILTER (WHERE g.canonical = 'Y'), '{}' ) canonical_users,
coalesce( array_agg(g.users) FILTER (WHERE g.canonical = 'N'), '{}' ) non_canonical_users
FROM groups g
GROUP BY g.id;
If you are looking for a modern answer to the general question of how to remove a NULL from an array, it is:
array_remove(your_array, NULL)
I was specifically curious about performance and wanted to compare this to the best possible alternative:
CREATE OR REPLACE FUNCTION strip_nulls(
IN array_in ANYARRAY
)
RETURNS anyarray AS
'
SELECT
array_agg(a)
FROM unnest(array_in) a
WHERE
a IS NOT NULL
;
'
LANGUAGE sql
;
Doing a pgbench test proved (with high confidence) that array_remove() is a little more than twice as fast. I did my test on double precision numbers with a variety of array sizes (10, 100 and 1000 elements) and random NULLs in between.
It's also worth noting that this can be used to remove blanks ('' != NULL). But the second parameter accepts anyelement
, and since it is most likely they you'd be indicating a blank with a string literal, make sure to cast it to the form you want, usually a non-array.
For example:
select array_remove(array['abc', ''], ''::text);
If you try:
select array_remove(array['abc', ''], '');
it will assume that the '' is TEXT[] (array) and will throw this error:
ERROR: malformed array literal: ""