在Postgres中使用NOT IN子句时的困惑

时间:2016-02-16 23:17:43

标签: sql postgresql null amazon-redshift

我使用以下查询在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))

我试图从id中排除lmsprovidergroups以获取groups的子集。为什么我必须先包含它(如在查询2中的内部查询中),然后再将其排除?

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

2 个答案:

答案 0 :(得分:2)

如果NOT IN条件的子查询返回至少一个NULL值,则NOT IN评估为“未知”,这导致根本没有匹配行。

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

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

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

答案 1 :(得分:1)

NOT IN (SELECT ...)几乎总是一个糟糕的选择。它不仅表现出“令人惊讶”的行为,而且两边都有NULL值(如果你不熟悉逻辑),它通常比NOT EXISTS的高级替代品慢:

SELECT id
FROM   flx2.groups g
WHERE  NOT EXISTS (SELECT 1 FROM flx2.lmsprovidergroups
                   WHERE  groupid = g.id);

还有其他标准技术: