处理jsonb_array_elements中的Null

时间:2019-07-19 18:36:31

标签: postgresql jsonb

我有2个表a和b

表a

id          |   name        | code
VARCHAR         VARCHAR       jsonb
1               xyz          [14, 15, 16 ]
2               abc          [null]
3               def          [null]

表b

id | name | code
1    xyz    [16, 15, 14 ]
2    abc        [null]

我想弄清楚代码在哪里不匹配相同的ID和名称。我对b b / c中的代码列进行排序,我知道相同,但排序方式不同

SELECT                  a.id,
                        a.name,
                        a.code,
                        c.id,
                        c.name,
                        c.code

                        FROM                a
                        FULL OUTER JOIN     (   SELECT          id,
                                                                name,
                                                                jsonb_agg(code ORDER BY code) AS code
                                                FROM        (
                                                                SELECT          id,
                                                                                name,
                                                                                jsonb_array_elements(code) AS code
                                                                FROM            b
                                                                GROUP BY        id,
                                                                                name,
                                                                                jsonb_array_elements(code)
                                                            ) t
                                                GROUP BY        id,
                                                                name
                                            ) c
                            ON              a.id = c.id
                            AND             a.name = c.name
                            AND             COALESCE (a.code, '[]'::jsonb) = COALESCE (c.code, '[]'::jsonb)
                        WHERE               (a.id IS NULL OR c.id IS NULL)

在这种情况下,我的答案应该只返回id = 3 b / c,而不是在b表中,但是我的查询也返回id = 2,而b / c我在内部子查询中没有很好地处理null情况 我如何处理内部子查询中的空用例?

1 个答案:

答案 0 :(得分:1)

demo:db<>fiddle

<@运算符检查左数组的所有元素是否都出现在右数组中。 @>进行其他操作。因此,使用两者可以确保两个数组包含相同的元素:

a.code @> b.code AND a.code <@ b.code

但是,如果一个数组包含重复项,则也会接受。因此[42,42][42]相同。如果您也想避免这种情况,则还应该检查数组长度

AND jsonb_array_length(a.code) = jsonb_array_length(b.code)

此外,您可能会检查两个值是否均为NULL。这种情况必须单独检查:

a.code IS NULL and b.code IS NULL

使用COALESCE函数的形式略短一些:

COALESCE(a.code, b.code) IS NULL

因此整个查询看起来像这样:

SELECT 
    *
FROM a
FULL OUTER JOIN b 
ON a.id = b.id AND a.name = b.name
AND (
    COALESCE(a.code, b.code) IS NULL            -- both null
    OR (a.code @> b.code AND a.code <@ b.code 
        AND jsonb_array_length(a.code) = jsonb_array_length(b.code) -- avoid accepting duplicates
    )
)

之后,您可以过滤NULL子句中的WHERE