Конкретные ключи Postgres в карте - PullRequest
0 голосов
/ 22 октября 2018

Какую комбинацию функций jsonb в Postgres 9.6 можно использовать для агрегирования по отдельным ключам карты?(Различные значения для одного и того же ключа приведут к случайному значению для этого ключа.)

Например, учитывая эти данные:

WITH tbl(id, j) as (
values
    (1, '{"key1": "val1"}'::jsonb),
    (1, '{"key2": "val2"}'),
    (1, '{"key2": "val2"}'),
    (2, '{"key3": "val3"}')
)
SELECT id, <what aggregate fn?>(data) FROM tbl GROUP BY 1

Как мы можем вернуть набор результатов, который дедуплицируется и объединяетсякак так?

id  | j
----|----------------------------------
1   | {"key1": "val1", "key2": "val2"}
2   | {"key3": "val3"}

1 Ответ

0 голосов
/ 22 октября 2018

Использование jsonb_object_agg() для пар (key, value) получено из jsonb_each(), используемых в боковом соединении:

with tbl(id, j) as (
values
    (1, '{"key1": "val1"}'::jsonb),
    (1, '{"key2": "val2"}'),
    (1, '{"key2": "val2"}'),
    (2, '{"key3": "val3"}')
)
select id, jsonb_object_agg(key, value)
from tbl 
cross join jsonb_each(j)
group by 1

 id |         jsonb_object_agg         
----+----------------------------------
  1 | {"key1": "val1", "key2": "val2"}
  2 | {"key3": "val3"}
(2 rows)

Обновление.Вы можете создать пользовательский агрегат:

create or replace function jsonb_object_merge(jsonb, jsonb)
returns jsonb language plpgsql as $$
begin
    return jsonb_object_agg(key, value)
    from ( 
        select key, value from jsonb_each($2)
        union   
        select key, value from jsonb_each($1)
    ) s;
end $$;

create aggregate my_jsonb_object_agg(jsonb)
(
    sfunc = jsonb_object_merge,
    stype = jsonb
);

, который может быть полезен в более сложных запросах (вместе с другими агрегатами):

with tbl(id, j, v) as (
values
    (1, '{"key1": "val1", "key4": "val4"}'::jsonb, 1),
    (1, '{"key2": "val2"}', 1),
    (1, '{"key2": "val3"}', 1),
    (2, '{"key3": "val3"}', 1)
)
select id, my_jsonb_object_agg(j), sum(v)
from tbl
group by 1

 id |               my_jsonb_object_agg                | sum 
----+--------------------------------------------------+-----
  1 | {"key1": "val1", "key2": "val2", "key4": "val4"} |   3
  2 | {"key3": "val3"}                                 |   1
(2 rows)    
...