2

With this query and recordset:

SELECT id, level FROM t;

id | level
----------
1  | a 
2  | a 
3  | a 
4  | b 
5  | b 
6  | c
7  | c

How to convert that to a JSON object, keyed by the level column and array aggregated on the id column? I don't know beforehand which levels exist.

{
  "a": [1, 2, 3],
  "b": [4, 5],
  "c": [6, 7]
}

I was hoping to do this:

SELECT json_object(
  array_agg(level),
  array_agg(ids)
)
FROM (
  SELECT level, array_agg(id::TEXT) ids
  FROM t
  GROUP BY level
) t

But it returns:

ERROR: cannot accumulate arrays of different dimensionality

If you feel like answering, here's t for your convenience

SELECT id, level
FROM ( VALUES
  (1, 'a'),
  (2, 'a'),
  (3, 'a'),
  (4, 'b'),
  (5, 'b'),
  (6, 'c'),
  (7, 'c')
) t(id, level);
Christiaan Westerbeek
  • 10,619
  • 13
  • 64
  • 89

1 Answers1

1

Use json(b) aggregate functions:

with my_table(id, level) as (
values
    (1, 'a'),
    (2, 'a'),
    (3, 'a'),
    (4, 'b'),
    (5, 'b'),
    (6, 'c'),
    (7, 'c')
)
select jsonb_object_agg(level, ids)
from (
    select level, jsonb_agg(id) as ids
    from my_table
    group by level
    ) s

              jsonb_object_agg              
--------------------------------------------
 {"a": [1, 2, 3], "b": [4, 5], "c": [6, 7]}
(1 row) 
klin
  • 112,967
  • 15
  • 204
  • 232