处理 jsonb_array_elements 中的 Null

Handle Null in jsonb_array_elements

我有 2 tables a 和 b

Table一个

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

Tableb

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)

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

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
    )
)

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