我有2个表a和b
id | name | code
VARCHAR VARCHAR jsonb
1 xyz [14, 15, 16 ]
2 abc [null]
3 def [null]
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情况 我如何处理内部子查询中的空用例?
答案 0 :(得分:1)
<@
运算符检查左数组的所有元素是否都出现在右数组中。 @>
进行其他操作。因此,使用两者可以确保两个数组包含相同的元素:
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
值