【问题标题】:How to unnest multiple postgres jsonb arrays in parallel如何并行取消嵌套多个postgres jsonb数组
【发布时间】:2021-02-05 22:47:12
【问题描述】:

我想一次遍历两个 jsonb 数组的元素。如果它只有一个数组,我知道我可以简单地使用 json_array_elements 一切都会好起来的。但是对于多个阵列,我很难想出一个解决方案。

类似于Unnest multiple arrays in parallel,但仅适用于 jsonb 数组。所以我知道对于常规的 postgres 数组有 unnest(anyarray, anyarray [, ...])。

这是我的示意图数据场景的 sn-p:

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

希望有人可以帮助我。

最好的祝愿 安迪

【问题讨论】:

    标签: sql postgresql jsonb sql-function


    【解决方案1】:

    使用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.

    【讨论】:

    • 您好,感谢您的回答。我只是尝试了一下并偶然发现了细节,这“仅适用于”相同长度的数组。您是否有一个解决方案也适用于不同长度的数组,而另一个数组的条目为零?
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 2015-03-06
      • 1970-01-01
      • 2023-04-07
      • 1970-01-01
      • 2015-06-18
      • 1970-01-01
      • 2022-01-02
      • 2017-07-13
      • 1970-01-01
      相关资源
      最近更新 更多