jsonpostgresqlpostgresql-9.4

json_array_elements with null values


I'm using PostgreSQL 9.4.5, 64 bit on windows. I've got some irregular sized arrays. I want to use json_array_elements to expand the arrays similar to the following code

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

However, when i run this, i get

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

The empty array in column aa is dropped on the floor along with the the value of 1 in column bb

I would like to get

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

Also, is this a bug in PostgreSQL?


Solution

  • You are using the right functions, but the wrong JOIN. If you (possibly) don't have rows on one side of the JOIN & you want to keep the rows from the other side of the JOIN & use NULLs to "pad" rows, you'll need an 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
    

    Note: it may seem strange to see on true as the joining condition, but it is actually quite general, when you are using LATERAL joins (which is implicit when you use a set returning function (SRF) directly in the FROM clause).

    http://rextester.com/KNW13145

    Edit: your original query does not involve a JOIN directly, but worse: you use a SRF in the SELECT clause. This is almost like a CROSS JOIN, but actually it has its own rules. Don't use that unless you know exactly what you are doing and why you need that.