在 Postgres 中使用 NOT IN 子句时的混淆

Confusion while using NOT IN clause in Postgres

我正在使用以下查询在 Amazon Redshift 上获得零结果。

查询 1:

SELECT id
FROM flx2.groups
WHERE id NOT IN (SELECT groupid FROM flx2.lmsprovidergroups)

现在,如果我稍微将其修改为:

,相同的查询就会开始给我结果

查询 2:

SELECT id
FROM flx2.groups
WHERE id NOT IN (SELECT id
                 FROM flx2.groups
                 WHERE id IN (SELECT groupid FROM flx2.lmsprovidergroups))

我正在尝试从 lmsprovidergroups 中排除 id 以从 groups 中获取一个子集。为什么我必须首先包含它(如在查询 2 的内部查询中)然后再次排除它?

就我而言,查询 1 与查询 2 完全相同。
为什么查询 2 有效而查询 1 无效?

如果 NOT IN 条件 returns 的子查询至少有一个 NULL 值,则 NOT IN 的计算结果为 "unknown",这导致没有行完全匹配。

您需要从子查询中删除 null 个值:

SELECT id
FROM flx2.groups
WHERE id NOT IN (SELECT groupid 
                 FROM flx2.lmsprovidergroups
                 WHERE groupid is not null)

你的第二个查询基本上做同样的事情:它从子查询中删除 null 值(假设 groups.id 不包含任何空值)

NOT IN (SELECT ...) 几乎总是一个糟糕的选择。它不仅表现出 "surprising" 两边都带有 NULL 值的行为(如果您不熟悉逻辑),它通常也比带有 NOT EXISTS:

的高级替代方案慢
SELECT id
FROM   flx2.groups g
WHERE  NOT EXISTS (SELECT 1 FROM flx2.lmsprovidergroups
                   WHERE  groupid = g.id);

还有其他标准技术:

  • Select rows which are not present in other table