Агрегатные конкатенированные массивы JSONB - PullRequest
1 голос
/ 24 июня 2019

Имея таблицу с именем example_table с одним столбцом с именем example_column типа JSONB и каждым значением в столбце, являющимся массивом.

Имея значения в 2 рядах: [1, 2] и[3]

Как я могу агрегировать-объединить значения в example_column?

Результат должен быть: [1, 2, 3]

Я пытался использовать:

select json_agg(example_column) from example_table

но это возвращает [[1, 2,], [3]]

Ответы [ 2 ]

1 голос
/ 24 июня 2019

Используйте функцию jsonb_array_elements(example_column), пример:

with example_table(example_column) as (
values
    (jsonb '[1, 2]'),
    (jsonb '[3]')
)

select jsonb_agg(value)
from example_table
cross join jsonb_array_elements(example_column) 

jsonb_agg 
-----------
 [1, 2, 3]
(1 row)

Вы можете определить порядок сортировки агрегированных элементов и / или удалить дубликаты, например ::

with example_table(id, example_column) as (
values
    (1, jsonb '[1, 2]'),
    (2, jsonb '[3]'),
    (3, jsonb '[3, 1]')
)

select 
    jsonb_agg(value order by id) as agg1,
    jsonb_agg(value order by value) as agg2,
    jsonb_agg(distinct value order by value) as agg3
from example_table
cross join jsonb_array_elements(example_column) 

      agg1       |      agg2       |   agg3    
-----------------+-----------------+-----------
 [1, 2, 3, 3, 1] | [1, 1, 2, 3, 3] | [1, 2, 3]
(1 row)
0 голосов
/ 25 июня 2019

Если вам нужно сделать это много, вы можете создать собственный агрегат для этого:

create function combine_jsonb_arrays(p_array_1 jsonb, p_array_2 jsonb) 
  returns jsonb
as
$$
  select jsonb_agg(t.val order by t.val)
  from (
    select *
    from jsonb_array_elements(p_array_1) as x1(val)
    union all
    select *
    from jsonb_array_elements(p_array_2) as x2(val)
  ) t;
$$
language sql;

create aggregate jsonb_elements_agg(jsonb)
(
  sfunc = combine_jsonb_arrays,
  stype = jsonb
);

Тогда вы можете использовать это так:

select jsonb_elements_agg(example_column)
from example_table;
...