简体   繁体   中英

Issue with array_agg method when aggregating arrays of different lengths

Here is a lateral query which is part of a bigger query:

lateral (
    select 
    array_agg(
            sh.dogsfilters
        ) filter (
            where 
                sh.dogsfilters is not null
        ) as dependencyOfFoods
    from 
        shelter sh
    where 
        sh.shelterid = ${shelterid}
) filtersOfAnimals,

the problem is with array_agg method as it fails when it has arrays with different lengths like this ("[[7, 9], [7, 9, 8], [8]]") !

The problem is easy to solve using json_agg but later in the query there's a any check like this:

...
where
    cd.dogsid = any(filtersOfAnimals.dependencyOfFoods)
and 
    ...
...

But as any will not work on json data which is prepared using json_agg so I can't use it instead of array_agg !

What might be a better solution to this?

It is ugly, but it works:

regexp_split_to_array(
          array_to_string(
             array_agg(
              array_to_string(value,',')
              ),','
          ),',')::integer[]

I don't know if this could be a valid solution from the the performance point of view ...

Unnest the arrays and re-aggregate:

lateral
(select array_agg(dogfilter) filter (where dogfilter is not null) as dependencyOfFoods
 from shelter sh cross join
      unnest(sh.dogsfilters) dogfilter
 where sh.shelterid = ${shelterid}
) filtersOfAnimals,

It is interesting that Postgres doesn't have a function that does this. BigQuery offers array_concat_agg() which does exactly what you want.

In PostgreSQL, you can define your own aggregates. I think that this one does what you want:

create function array_concat_agg_tran(anyarray,anyarray) returns anyarray language sql
    as $$ select $1||$2 $$;
create aggregate array_concat_agg(anyarray) (sfunc=array_concat_agg_tran, stype=anyarray);

Then:

 select array_concat_agg(x) from (values (ARRAY[1,2]),(ARRAY[3,4,5])) f(x);
 array_concat_agg 
------------------
 {1,2,3,4,5}

With a bit more work, you could make it parallelizable as well.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM