使用串联(||)运算符时,Postgres SQL不返回预期的行

时间:2014-03-27 19:22:34

标签: postgresql concatenation string-concatenation pgadmin

我有一张包含生产数据的表,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版本返回剩余的行。

有没有人有任何想法?

1 个答案:

答案 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的常用方法。