如何有条件地将元素添加到jsonb数组?

时间:2019-07-19 18:39:32

标签: postgresql jsonb

有没有一种方法可以有条件地将元素添加到postgres jsonb数组中?我正在尝试构造一个数组,以将其添加到始终需要大多数元素的较大对象中,但我希望其中一些是可选的。

作为简化示例:

select jsonb_build_array(
    jsonb_build_object('a', a),
    jsonb_build_object('b', b),
    jsonb_build_object('c', c),
    case when a + b <> c then
        jsonb_build_object('error', c - (a + b))
    end
) from ( values (2, 2, 5) ) as things (a,b,c);

这在a + b <> c时工作正常,但是当a + b = c我在数组中得到null时,例如

sophia=> \i ~/cc/dpdb/migration/foo.sql
              jsonb_build_array               
----------------------------------------------
 [{"a": 2}, {"b": 2}, {"c": 5}, {"error": 1}]
(1 row)

sophia=> \i ~/cc/dpdb/migration/foo.sql
          jsonb_build_array           
--------------------------------------
 [{"a": 2}, {"b": 2}, {"c": 4}, null]
(1 row)

sophia=>

有没有一种方法可以添加不带null的元素,或者如果添加了元素,请删除null?显然,我可以将整个程序段放在一个案例中,并复制前几行,但这将非常丑陋且冗长。有jsonb_strip_nulls,但仅适用于数组而不是对象。

1 个答案:

答案 0 :(得分:1)

您必须使用第二步,因为您不能在语法中创建“无元素”。您要么用两个不同的数组创建将这两种情况真正分开,要么随后必须有条件地调整创建的数组:

demo:db<>fiddle

SELECT 
    CASE WHEN a + b <> c THEN
        my_array || jsonb_build_object('error', c - (a + b))
    ELSE
        my_array
    END 
FROM (
    select 
        a, b, c,
        jsonb_build_array(
            jsonb_build_object('a', a),
            jsonb_build_object('b', b),
            jsonb_build_object('c', c)
        ) AS my_array
    from ( values (2, 2, 5), (2, 2, 4) ) as things (a,b,c)
) s