如何并行取消嵌套多个 postgres jsonb 数组
How to unnest multiple postgres jsonb arrays in parallel
我想一次遍历两个 jsonb 数组的元素。如果它只是一个数组,我知道我可以简单地使用 json_array_elements 一切都会好起来的。但是对于多个阵列,我很难想出一个解决方案。
类似于,但仅适用于 jsonb 数组。所以我知道对于常规的 postgres 数组有 unnest(anyarray, anyarray [ ...]).
这是我的示意图数据场景的片段:
SELECT *
FROM jsonb_to_recordset('[{"id": 0, "array_a": ["a", "c"], "array_b": ["b" , "d"]}]')
AS example(id jsonb, array_a jsonb, array_b jsonb)
我想转换成:
a | b
c | d
希望有人能帮助我。
祝福
安迪
使用 with ordinality
和连接将值压缩在一起:
with invars as (
SELECT *
FROM jsonb_to_recordset('[{"id": 0, "array_a": ["a", "c"], "array_b": ["b" , "d"]}]')
AS example(id jsonb, array_a jsonb, array_b jsonb)
)
select a1, b1
from invars
cross join lateral jsonb_array_elements(array_a) with ordinality as ela(a1, rn)
cross join lateral jsonb_array_elements(array_b) with ordinality as elb(b1, rn)
where ela.rn = elb.rn;
如果数组可以有不同的长度,那么即使可能有更优雅的解决方案,这也可以工作:
with invars as (
SELECT *
FROM jsonb_to_recordset('[{"id": 0, "array_a": ["a", "c", "e"], "array_b": ["b" , "d", "f", "h"]}]')
AS example(id jsonb, array_a jsonb, array_b jsonb)
), a_side as (
select a1, rn
from invars
cross join lateral jsonb_array_elements(array_a) with ordinality as ela(a1, rn)
), b_side as (
select b1, rn
from invars
cross join lateral jsonb_array_elements(array_b) with ordinality as elb(b1, rn)
)
select a1, b1
from a_side
full join b_side
on a_side.rn = b_side.rn
;
您可以连续应用 JSONB_ARRAY_ELEMENTS()
和 JSONB_ARRAY_ELEMENTS_TEXT()
函数,包括 ORDINALITY
选项
WITH t2 AS
(
SELECT (elm -> 'array_a')::JSONB AS a, (elm -> 'array_b')::JSONB AS b
FROM t
CROSS JOIN JSONB_ARRAY_ELEMENTS(jsdata)
WITH ORDINALITY AS q(elm, i)
)
SELECT col1, col2
FROM t2
JOIN JSONB_ARRAY_ELEMENTS_TEXT(a) WITH ORDINALITY AS q1(col1, i) ON TRUE
JOIN JSONB_ARRAY_ELEMENTS_TEXT(b) WITH ORDINALITY AS q2(col2, j) ON i=j
我想一次遍历两个 jsonb 数组的元素。如果它只是一个数组,我知道我可以简单地使用 json_array_elements 一切都会好起来的。但是对于多个阵列,我很难想出一个解决方案。
类似于
这是我的示意图数据场景的片段:
SELECT *
FROM jsonb_to_recordset('[{"id": 0, "array_a": ["a", "c"], "array_b": ["b" , "d"]}]')
AS example(id jsonb, array_a jsonb, array_b jsonb)
我想转换成:
a | b
c | d
希望有人能帮助我。
祝福 安迪
使用 with ordinality
和连接将值压缩在一起:
with invars as (
SELECT *
FROM jsonb_to_recordset('[{"id": 0, "array_a": ["a", "c"], "array_b": ["b" , "d"]}]')
AS example(id jsonb, array_a jsonb, array_b jsonb)
)
select a1, b1
from invars
cross join lateral jsonb_array_elements(array_a) with ordinality as ela(a1, rn)
cross join lateral jsonb_array_elements(array_b) with ordinality as elb(b1, rn)
where ela.rn = elb.rn;
如果数组可以有不同的长度,那么即使可能有更优雅的解决方案,这也可以工作:
with invars as (
SELECT *
FROM jsonb_to_recordset('[{"id": 0, "array_a": ["a", "c", "e"], "array_b": ["b" , "d", "f", "h"]}]')
AS example(id jsonb, array_a jsonb, array_b jsonb)
), a_side as (
select a1, rn
from invars
cross join lateral jsonb_array_elements(array_a) with ordinality as ela(a1, rn)
), b_side as (
select b1, rn
from invars
cross join lateral jsonb_array_elements(array_b) with ordinality as elb(b1, rn)
)
select a1, b1
from a_side
full join b_side
on a_side.rn = b_side.rn
;
您可以连续应用 JSONB_ARRAY_ELEMENTS()
和 JSONB_ARRAY_ELEMENTS_TEXT()
函数,包括 ORDINALITY
选项
WITH t2 AS
(
SELECT (elm -> 'array_a')::JSONB AS a, (elm -> 'array_b')::JSONB AS b
FROM t
CROSS JOIN JSONB_ARRAY_ELEMENTS(jsdata)
WITH ORDINALITY AS q(elm, i)
)
SELECT col1, col2
FROM t2
JOIN JSONB_ARRAY_ELEMENTS_TEXT(a) WITH ORDINALITY AS q1(col1, i) ON TRUE
JOIN JSONB_ARRAY_ELEMENTS_TEXT(b) WITH ORDINALITY AS q2(col2, j) ON i=j