在 Postgres 中使用 NOT IN 子句时的困惑
Posted
技术标签:
【中文标题】在 Postgres 中使用 NOT IN 子句时的困惑【英文标题】:Confusion while using NOT IN clause in Postgres 【发布时间】:2016-02-16 23:17:43 【问题描述】:我正在使用以下查询在 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 无效?
【问题讨论】:
使用LEFT JOIN
会更容易。而且这两个查询完全不同。
@JakubKania:您是否可以阐明这些查询有何不同?我知道我想出了它们,但我看不出它们有什么不同。我的意思是,当然,一个产生结果,另一个没有,它们必须不同。但是如何,为什么?
flx2.groups.id
中有任何nulls
?顺便说一句:IN
或 NOT IN
子句的子选择中的 distinct
没有用
@a_horse_with_no_name:我同意 distinct
在这种情况下没用。在flx2.groups.id
中没有nulls
。
flx2.lmsprovidergroups.groupid
中有空值吗?
【参考方案1】:
如果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
不包含任何空值)
【讨论】:
【参考方案2】:NOT IN (SELECT ...)
几乎总是一个糟糕的选择。它不仅表现出“令人惊讶”的行为,两边都有 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【讨论】:
你让我看到了一些我不知道的事情。非常感谢。在遇到此问题之前,我几乎在编写的每个查询中都使用了NOT IN
。现在我知道得更多了,谢谢你:)。以上是关于在 Postgres 中使用 NOT IN 子句时的困惑的主要内容,如果未能解决你的问题,请参考以下文章
如何在带有 Postgres 的动态框架中使用窗口函数中的列值?
使用 liquibase 在 postgres 中删除索引的问题