如何并行取消嵌套多个 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;

Working fiddle.

如果数组可以有不同的长度,那么即使可能有更优雅的解决方案,这也可以工作:

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
;

Updated Fiddle.

您可以连续应用 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 

Demo