【问题标题】:Confusion while using NOT IN clause in Postgres在 Postgres 中使用 NOT IN 子句时的困惑
【发布时间】: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?顺便说一句:INNOT IN 子句的子选择中的 distinct 没有用
  • @a_horse_with_no_name:我同意 distinct 在这种情况下没用。在flx2.groups.id 中没有nulls
  • flx2.lmsprovidergroups.groupid 中有空值吗?

标签: sql postgresql null amazon-redshift


【解决方案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);
    

    还有其他标准技术:

    【讨论】:

    • 你让我看到了一些我不知道的事情。非常感谢。在遇到此问题之前,我几乎在编写的每个查询中都使用了NOT IN。现在我知道得更多了,谢谢你:)。
    猜你喜欢
    • 2018-03-23
    • 1970-01-01
    • 2016-10-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-14
    • 1970-01-01
    • 2011-01-12
    相关资源
    最近更新 更多