我有一张包含生产数据的表,Prod。 Prod,A和B中有两个字段,我用它们作为键(两者都是VARCHAR)。我有另一个表,舞台,我想导入Prod。但是,在导入Stage之前,我想检查Stage是否包含已在Prod中的行。将从导入中排除任何重复的行。
我遇到的问题如下:
当我运行诸如
之类的查询时SELECT A, B
FROM Stage
WHERE A || B NOT IN (
SELECT A || B
FROM Prod
)
我希望我会收到所有非重复(新)条目的列表。但是,我没有收到任何结果。
此外,我跑的时候
SELECT A, B
FROM Stage
WHERE A || B IN (
SELECT A || B
FROM Prod
)
唯一的区别是将NOT IN
更改为IN
,我只返回返回的表的子集,而不是我期望的整个表。
我知道这个问题与串联(||)运算符有关,因为当我运行
时SELECT A
FROM Stage
WHERE A NOT IN (
SELECT A FROM Prod
)
返回行,查询的IN
版本返回剩余的行。
有没有人有任何想法?
答案 0 :(得分:1)
您的陈述有两个问题:
首先:使用字符串连接不会像预期的那样工作,因为比较无法区分元组('a','bc')
和('ab','c')
(因为两者都会产生相同的连接值。
使用真正的元组比较是正确的方法:
where (a,b) not in (select a,b ...)
现在到了第二个问题:
“{1}}比较,其中”比较列表“包含NOT IN
将始终返回空结果,因为与NULL
的任何比较都会产生”未知“,因此数据库无法可靠地确定是否“左手边”的值是否在该列表中。
您使用以下内容撰写了该文章:null
返回了一些内容,这意味着SELECT A FROM Stage WHERE A NOT IN (SELECT A FROM Prod)
中没有null
值,但显然位于prod.a
中。
如果您想忽略prod.b
值,可以使用以下内容:
null
另一种选择是对待select a,b
from stage
where (a,b) not in (select a,b
from prod
where b is not null);
还有别的东西,例如一个空字符串:
null
使用select a,b
from stage
where (a,coalesce(b, '')) not in (select a, coalesce(b, '')
from prod);
运算符时不会发生此问题,因此
in
即使使用select a,b
from stage
where (a,b) in (select a,b
from prod);
值也可以安全使用。
但是,如果您将这两列用作“键”,则首先不应在其中包含null
值。
顺便说一下:这不是Postgres特有的,这就是SQL的常用方法。