【问题标题】:json_array_elements with null values具有空值的 json_array_elements
【发布时间】:2017-04-24 21:30:53
【问题描述】:

我在 Windows 上使用 PostgreSQL 9.4.5,64 位。 我有一些不规则大小的数组。我想用 json_array_elements展开数组类似如下代码

with outside as (select (json_array_elements('[[],[11],[21,22,23]]'::json)) aa, json_array_elements('[1,2,3]'::json)bb) 
select json_array_elements_text(aa), bb from outside

但是,当我运行它时,我得到了

aa | bb
------- 
11 |  2
21 |  3
22 |  3
23 |  3

aa 列中的空数组连同 bb 列中的值 1 一起掉落在地板上

我想得到

aa   | bb
---------- 
null |  1
11   |  2
21   |  3
22   |  3
23   |  3

另外,这是 PostgreSQL 中的错误吗?

【问题讨论】:

    标签: json postgresql postgresql-9.4


    【解决方案1】:

    您使用了正确的功能,但使用了错误的JOIN。如果您(可能)在JOIN 的一侧没有行并且您想保留JOIN 另一侧的行并使用NULLs 来“填充”行,您需要OUTER JOIN:

    with outside as (
        select json_array_elements('[[],[11],[21,22,23]]') aa,
               json_array_elements('[1,2,3]') bb
    ) 
    select    a, bb
    from      outside
    left join json_array_elements_text(aa) a on true
    

    注意可能on true视为加入条件似乎很奇怪,但当您使用LATERAL joins(即直接在 FROM 子句中使用集合返回函数 (SRF) 时隐含)。

    http://rextester.com/KNW13145

    编辑:您的原始查询不直接涉及JOIN,但更糟糕的是:您在SELECT 子句中使用了SRF。这几乎类似于CROSS JOIN,但实际上是it has its own rulesDon't use that 除非您确切地知道自己在做什么以及为什么需要它。

    【讨论】:

    • 谢谢 - 很好的回答,左连接比 klin 的案例语句更干净
    【解决方案2】:

    这不是错误。 json_array_elements_text('[null]') 返回 nulljson_array_elements_text('[]') 不返回任何内容。

    with outside as (
        select (
            json_array_elements('[[],[11],[21,22,23]]'::json)) aa, 
            json_array_elements('[1,2,3]'::json) bb
    ) 
    select elem as aa, bb
    from outside,
    json_array_elements_text(case when aa::text = '[]' then '[null]'::json else aa end) elem;
    
     aa | bb 
    ----+----
        | 1
     11 | 2
     21 | 3
     22 | 3
     23 | 3
    (5 rows)    
    

    【讨论】:

    • 我同意 json_array_elements_text 像你描述的那样工作,为什么这是正确的行为?
    • 因为'[null]'::json'[]'::json是有区别的。第一个数组包含 null,第二个为空。该函数无法从空数组返回任何内容。
    【解决方案3】:

    解决我自己的问题,我有一个可能的答案,但似乎一团糟

    With initial as (select '[[],[11],[21,22,23]]'::json as a, '[1,2,3]'::json as b),
        Q1 as (select json_array_elements(a) as aa, json_array_elements(b) bb from initial),
        Q2 as (select ARRAY[aa->>0, aa->>1, aa->>2] as aaa, bb as bbb, ARRAY[0,1,2] as ccc from q1), 
        -- where the indicices are computed in a separate query by looping from 0 to json_array_length(...)
        Q3 as (select unnest(aaa) as aaaa, bbb as bbbb, unnest(ccc) as cccc from q2)
    
    Select aaaa, bbbb from q3 where aaaa is not null or cccc = 0
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-13
      相关资源
      最近更新 更多