PostgreSQL使用JSON数组合并列

时间:2019-05-13 15:40:58

标签: arrays json postgresql coalesce

假设我们有以下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_*,我必须以半恒定的方式行驶。 “半”表示某些元素是变化的(键:var123xyzhtguy1)。它们的组合数量有限,因此我可以通过在代码中编写不同的方式来处理它们,例如:

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()来获得一个列{具有非NULL值的{1}}:

col

执行此查询后,我得到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

1 个答案:

答案 0 :(得分:1)

如何完全扩展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