Postgresql 使用 JSON 数组合并列
Postgresql coalesce columns with JSON array
假设我们有以下 JSON 对象:
{"key_to_array":[{"key1":"value1","key2":{"var123":{"xyz":"I_need_version_1"}}},{"key1":"value1","key2":{"htg":{"uy1":"I_need_version_2"}}}]}}
插入一个 table:
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_*
我必须走半恒定的路。 'Semi' 表示某些元素在变化(键: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
完全扩展 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
假设我们有以下 JSON 对象:
{"key_to_array":[{"key1":"value1","key2":{"var123":{"xyz":"I_need_version_1"}}},{"key1":"value1","key2":{"htg":{"uy1":"I_need_version_2"}}}]}}
插入一个 table:
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_*
我必须走半恒定的路。 'Semi' 表示某些元素在变化(键: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
完全扩展 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