Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Postgres: aggregate column into array

Tags:

postgresql

I have the following two tables:

# select * from list;
  list_id |         name
 ---------+----------------------
        9 | Popular
       11 | Recommended

and

# select * from list_item;
 list_id | game_id | position 
---------+---------+----------
      11 |       2 |        0
       9 |      10 |        1
      11 |       5 |        1
      11 |       4 |        4
      11 |       6 |        2
      11 |       7 |        3
       9 |       3 |        0

I want an array of game IDs per list like so:

 list_id |     name    | game_ids
---------+-------------+------------
       9 | Popular     | {3,10}
      11 | Recommended | {2,5,6,7,4}

I came up with the following solution but it seems rather complicated especially the bit where I get the completed array using distinct on and last_value:

with w as (
  select
    list_id,
    name,
    array_agg(game_id) over (partition by list_id order by position)
  from list
  join list_item
  using (list_id)
)
select
  distinct on (list_id)
  list_id,
  name,
  last_value(array_agg) over (partition by list_id)
from w

Any suggestions how to simplify this?

like image 382
peterwimsey Avatar asked Aug 08 '16 19:08

peterwimsey


People also ask

What is Array_agg in PostgreSQL?

PostgreSQL ARRAY_AGG() function is an aggregate function that accepts a set of values and returns an array where each value in the input set is assigned to an element of the array. Syntax: ARRAY_AGG(expression [ORDER BY [sort_expression {ASC | DESC}], [...]) The ORDER BY clause is an voluntary clause.

How do I create aggregate function in PostgreSQL?

To define a new aggregate function, one selects a data type for the state value, an initial value for the state, and a state transition function. The state transition function takes the previous state value and the aggregate's input value(s) for the current row, and returns a new state value.

Is coalesce an aggregate function?

The coalesce function can be used to substitute zero or an empty array for null when necessary. Here ANY can be considered either as introducing a subquery, or as being an aggregate function, if the subquery returns one row with a Boolean value.

What is Jsonb_agg?

The jsonb_agg(expression) function aggregates all values indicated by its expression, returning the values (including nulls) as a jsonb array.


1 Answers

Here is a better solution as suggested by Abelisto in the comments:

select
  list_id,
  name,
  array_agg(game_id order by position)
from list
join list_item
using (list_id)
group by list_id, name
like image 158
peterwimsey Avatar answered Sep 28 '22 13:09

peterwimsey