34

I would like to concatenate two columns using a group-by query resulting in an array separed with brackets. I know this question is related to this question, but as usual my use-case is a little different.

A simple example (also as SQL Fiddle). Currently my query returns the following:

ID  X   Y
3   0.5 2.71
3   1.0 2.50
3   1.5 2.33
6   0.5 2.73
6   1.5 2.77

But where I would like concatenate/aggregate the X/Y columns to get the following:

ID  XY
3   [[0.5,2.71],[1.0,2.50],[1.5,2.33]]
6   [[0.5,2.73],[1.5,2.77]]

Currently I've tried to concatenate the columns into one as follows:

SELECT "ID",concat_ws(', ',"X", "Y") as XY FROM Table1;

Which returns:

ID  xy
3   0.5, 2.71
3   1, 2.50
3   1.5, 2.33
6   0.5, 2.73

And used array_agg():

SELECT "ID",array_to_string(array_agg("X"),',') AS XY
FROM Table1
GROUP BY "ID";

Resulting in:

ID  xy
3   0.5,1,1.5
6   0.5

I feel I'm getting closer, but a helping hand would be really appreciated.

Community
  • 1
  • 1
Mattijn
  • 12,975
  • 15
  • 45
  • 68

2 Answers2

61

Create an array from the two columns, the aggregate the array:

select id, array_agg(array[x,y])
from the_table
group by id;

Note that the default text representation of arrays uses curly braces ( {..}) not square brackets ([..])

13

In Postgres 9.5 or later a overloaded variant of array_agg() takes array input as provided by @a_horse.

SELECT id, array_agg(ARRAY[x, y]) AS xy
FROM   tbl
GROUP  BY id;

The manual:

Concatenates all the input arrays into an array of one higher dimension. (The inputs must all have the same dimensionality, and cannot be empty or null.)


In older versions, this isn't implemented yet. You can create your own aggregate function (once per database) to achieve the same:

CREATE AGGREGATE array_agg_mult (anyarray)  (
    SFUNC     = array_cat
  , STYPE     = anyarray
  , INITCOND  = '{}'
);

Then:

SELECT id, array_agg_mult(ARRAY[ARRAY[x,y]]) AS xy  -- note the 2D array!
FROM   tbl
GROUP  BY id;

Details:

Or you can concatenate a string:

SELECT id, '[[' || string_agg(concat_ws(',', x, y), '],[') || ']]' AS xy
FROM   tbl
GROUP  BY id;

Produces your desired result exactly. A string, not an array.

Erwin Brandstetter
  • 605,456
  • 145
  • 1,078
  • 1,228