PostgreSQL中的JSON重新格式化
在一个PostgreSQL表中,我有一个带有JSON的列,类似于:PostgreSQL中的JSON重新格式化,json,postgresql,Json,Postgresql,在一个PostgreSQL表中,我有一个带有JSON的列,类似于: {“elements”:[{“val”:“value1”,“column”:“column1”},{“val”:“val2”,“column”:“column2”},…]} 是否可以将其转换为结果集,如: column1 | column2 | ... ----------------------- value1 | value2 | ... 我研究了PostgreSQL JSON函数,但没有找到答案。在执行查询之前,需要
{“elements”:[{“val”:“value1”,“column”:“column1”},{“val”:“val2”,“column”:“column2”},…]}
是否可以将其转换为结果集,如:
column1 | column2 | ...
-----------------------
value1 | value2 | ...
我研究了PostgreSQL JSON函数,但没有找到答案。在执行查询之前,需要知道查询的列数,因此必须为数组中的每个可能列编写一个表达式 对于Postgres 12,您可以使用JSON/Path表达式执行此操作:
select jsonb_path_query_first(input -> 'elements', '$[*].val ? ($.column == "column1")' ) #>> '{}' as column_1,
jsonb_path_query_first(input -> 'elements', '$[*].val ? ($.column == "column2")' ) #>> '{}' as column_2
from data;
您需要为数组中的每个可能列重复jsonb\u path\u query\u first()
部分
#>{}
用于将函数返回的JSONB值转换为文本
值 在执行查询之前,需要知道查询的列数,因此必须为数组中的每个可能列编写一个表达式
对于Postgres 12,您可以使用JSON/Path表达式执行此操作:
select jsonb_path_query_first(input -> 'elements', '$[*].val ? ($.column == "column1")' ) #>> '{}' as column_1,
jsonb_path_query_first(input -> 'elements', '$[*].val ? ($.column == "column2")' ) #>> '{}' as column_2
from data;
您需要为数组中的每个可能列重复jsonb\u path\u query\u first()
部分
#>{}
用于将函数返回的JSONB值转换为文本
值 您可以使用json_to_recordset
函数将json转换为行集。无论如何,最后的行集不能有动态的列数,也就是说,无论您选择什么解决方案,您都必须以某种方式显式地列出它们
例如,在select子句中,手动转换1:1转换的JSON时:
with t(d) as (values
('{"elements":[{"val":"value1", "column":"column1"}, {"val":"val2", "column":"column2"}]}'::json)
), matrix(val,col) as (
select x.val, x."column"
from t
inner join lateral json_to_recordset((t.d->>'elements')::json) as x(val text, "column" text) on true
)
select (select val from matrix where col = 'column1') as column1
, (select val from matrix where col = 'column2') as column2
或者在使用交叉表扩展名时,在中作为x(第1列文本,第2列文本)
子句(请参阅)
或者以某种方式转换为xml JSON 您可以使用json_to_recordset
函数将json转换为行集。无论如何,最后的行集不能有动态的列数,也就是说,无论您选择什么解决方案,您都必须以某种方式显式地列出它们
例如,在select子句中,手动转换1:1转换的JSON时:
with t(d) as (values
('{"elements":[{"val":"value1", "column":"column1"}, {"val":"val2", "column":"column2"}]}'::json)
), matrix(val,col) as (
select x.val, x."column"
from t
inner join lateral json_to_recordset((t.d->>'elements')::json) as x(val text, "column" text) on true
)
select (select val from matrix where col = 'column1') as column1
, (select val from matrix where col = 'column2') as column2
或者在使用交叉表扩展名时,在中作为x(第1列文本,第2列文本)
子句(请参阅)
或者以某种方式转换为xml JSON 此示例JSON值通过此查询使用JSON\u array\u elements\u text()
和JSON\u each()
函数,动态地取消填充到col
和val
列中
SELECT json_array_elements_text(v)::json->>'column' AS col,
json_array_elements_text(v)::json->>'val' AS val
FROM tab t
CROSS JOIN json_each(jsval) as js(k,v)
但是,将来自上述查询的结果旋转到各个列时,应根据结果查询的列数,以使用条件聚合的方式单独列出这些列:
SELECT MAX(val) FILTER (WHERE col = 'column1') as column1,
MAX(val) FILTER (WHERE col = 'column2') as column2,
MAX(val) FILTER (WHERE col = 'column3') as column3
FROM
(
SELECT json_array_elements_text(v)::json->>'column' AS col,
json_array_elements_text(v)::json->>'val' AS val
FROM tab t
CROSS JOIN json_each(jsval) as js(k,v)
) q
此示例JSON值通过使用JSON\u array\u elements\u text()
和JSON\u each()
函数通过此查询动态取消填充到col
和val
列中
SELECT json_array_elements_text(v)::json->>'column' AS col,
json_array_elements_text(v)::json->>'val' AS val
FROM tab t
CROSS JOIN json_each(jsval) as js(k,v)
但是,将来自上述查询的结果旋转到各个列时,应根据结果查询的列数,以使用条件聚合的方式单独列出这些列:
SELECT MAX(val) FILTER (WHERE col = 'column1') as column1,
MAX(val) FILTER (WHERE col = 'column2') as column2,
MAX(val) FILTER (WHERE col = 'column3') as column3
FROM
(
SELECT json_array_elements_text(v)::json->>'column' AS col,
json_array_elements_text(v)::json->>'val' AS val
FROM tab t
CROSS JOIN json_each(jsval) as js(k,v)
) q
基于@a_horse_和_no_name提案:
select
jsonb_path_query_first(raw_data_1thbase.data -> 'elements', '$[*] ? (@.column == "column1").val' ) #>> '{}' as column1,
jsonb_path_query_first(raw_data_1thbase.data -> 'elements', '$[*] ? (@.column == "column2").val' ) #>> '{}' as column2
from data;
为我工作。基于@a_horse_和_no_name提案:
select
jsonb_path_query_first(raw_data_1thbase.data -> 'elements', '$[*] ? (@.column == "column1").val' ) #>> '{}' as column1,
jsonb_path_query_first(raw_data_1thbase.data -> 'elements', '$[*] ? (@.column == "column2").val' ) #>> '{}' as column2
from data;
为我工作。您想更改您的模式吗?或者您希望在给定当前架构的情况下将其更改为柱状视图?第二个选项。我想在columnar视图中获取SELECT查询的结果集,而不仅仅是JSON字符串。您使用的是哪个Postgres版本?你有列数的上限吗?@a_horse_,名称为PostgreSQL v.12.2。我知道,这是有限制的,但我没有面对它。请不要把解决方案放在这个问题上。添加一个新答案,然后将其删除。否则,您的问题将保持“未解决”。如果给定的答案都不能解决您的问题,那么添加并接受您自己的答案是完全可以的。您想更改您的模式吗?或者您希望在给定当前架构的情况下将其更改为柱状视图?第二个选项。我想在columnar视图中获取SELECT查询的结果集,而不仅仅是JSON字符串。您使用的是哪个Postgres版本?你有列数的上限吗?@a_horse_,名称为PostgreSQL v.12.2。我知道,这是有限制的,但我没有面对它。请不要把解决方案放在这个问题上。添加一个新答案,然后将其删除。否则,您的问题将保持“未解决”。如果给定的答案都不能解决您的问题,那么添加并接受您自己的答案是非常好的。我尝试了这个方法,但它为每列返回相同的值。但是更改为“输入->'elements','$[*]?(@.column==“column1”).val')#>>'{}'”时job@A.Sizov:不知道,上面的方法对我有效:我尝试了这个方法,但它为每个列返回相同的值。但是更改为“输入->'elements','$[*]?(@.column==“column1”).val')#>>'{}'”时job@A.Sizov:不知道,上面这些对我很有用: