Postgresql объединяет столбцы с массивом JSON - PullRequest
0 голосов
/ 13 мая 2019

Допустим, у нас есть следующий объект JSON:

{"key_to_array":[{"key1":"value1","key2":{"var123":{"xyz":"I_need_version_1"}}},{"key1":"value1","key2":{"htg":{"uy1":"I_need_version_2"}}}]}}

, вставленный в таблицу:

drop table if exists modeling.modeling.pl_nested_json_array;
select '{"key_to_array":[{"key1":"value1","key2":{"var123":{"xyz":"I_need_version_1"}}},{"key1":"value1","key2":{"htg":{"uy1":"I_need_version_2"}}}]}' as json_data
into modeling.modeling.pl_nested_json_array
from modeling.modeling.some_other_table
limit 1;

Чтобы добраться до I_need_version_*, я должен проехать полупостоянный путь.«Полу» означает, что некоторые элементы различаются (ключи: var123, xyz, htg, uy1).Существует конечное число их комбинаций, поэтому я могу обработать их, написав в своем коде различные способы, такие как:

json_array_elements(cast(json_data as json) -> 'key_to_array') -> 'key2' -> 'var123' ->> 'xyz' as col1

Проблема заключается в том, что мой текущий подход:

/* many columns version - unwanted */
select 
    json_array_elements(cast(json_data as json) -> 'key_to_array') ->> 'key1' as key1,
    json_array_elements(cast(json_data as json) -> 'key_to_array') -> 'key2' -> 'var123' ->> 'xyz' as col1,
    json_array_elements(cast(json_data as json) -> 'key_to_array') -> 'key2' -> 'htg' ->> 'uy1' as col2
from modeling.modeling.pl_nested_json_array;

производитстолько столбцов, сколько есть способов добраться до I_need_version_*.Поскольку для каждого JSON_data допустим только один способ (создает I_need_version_*), остальные столбцы col* имеют значение NULL, я решил использовать COALESCE(), чтобы получить один столбец col со значением, отличным от NULL.:

select 
    json_array_elements(cast(json_data as json) -> 'key_to_array') ->> 'key1' as key1,
    coalesce(
    json_array_elements(cast(json_data as json) -> 'key_to_array') -> 'key2' -> 'var123' ->> 'xyz',
    json_array_elements(cast(json_data as json) -> 'key_to_array') -> 'key2' -> 'htg' ->> 'uy1') as col
from modeling.modeling.pl_nested_json_array;

После выполнения этого запроса я получаю ERROR: set-returning functions are not allowed in COALESCE.

Вывод, который я сейчас получаю:

key1          col1               col2
value1        I_need_version_1   [NULL]
value1        [NULL]             I_need_version_2

Что я хотел бы получить:

key1     col
value1   I_need_version_1
value1   I_need_version_2

1 Ответ

1 голос
/ 14 мая 2019

А как насчет полного расширения json и выбора элементов, которые вам нужны? Я не уверен, сколько строк мы говорим, поэтому производительность может быть проблемой, но по крайней мере вам не нужно беспокоиться о разных путях.

WITH data as (
  SELECT '{"key_to_array":[{"key1":"value1","key2":{"var123":{"xyz":"I_need_version_1"}}},{"key1":"value1","key2":{"htg":{"uy1":"I_need_version_2"}}}]}'::jsonb as data
)
SELECT key1, k3_val
FROM data
CROSS JOIN jsonb_array_elements(data.data -> 'key_to_array') arr(elem)
CROSS JOIN jsonb_to_record(elem) as x(key1 text, key2 jsonb)
CROSS JOIN jsonb_each(key2) as k2(k2_key, k2_val)
CROSS JOIN jsonb_each_text(k2_val) as k3(k3_key, k3_val)
WHERE k3_val like 'I_need_version_%'
;
key1    k3_val
value1  I_need_version_1
value1  I_need_version_2
...