【问题标题】:Postgres NOT IN (null) gives no resultPostgres NOT IN (null) 没有结果
【发布时间】:2013-07-26 11:20:18
【问题描述】:

我在这个查询中使用 Postgres

select 
*
from Entity this_ 
where 
(this_.ID not in (null))

为什么这没有给我任何结果?我希望得到所有 id 不为空的行

(this_.ID not in (1))

我得到了预期的结果

【问题讨论】:

    标签: postgresql null notin


    【解决方案1】:

    [not] in (null) 的结果将始终为空。要与 null 进行比较,您需要 is [not] nullis [not] distinct from null

    select *
    from Entity this_ 
    where this_.ID is not null
    

    如果你想要where (ID not in (1,null)),就像你的评论一样,你可以这样做

    where ID is not null and ID not in (1)
    

    【讨论】:

    • 表示不可能选择“从实体中选择*(ID不在(1,null))”?
    【解决方案2】:

    PostgreSQL 使用 NULL 作为未定义的值。
    您要求的是返回不在列表中或未定义值中的项目。由于 undefined 意味着你不知道里面有什么,PostgreSQL 不会返回任何项目,因为根本无法响应请求。
    而请求:

    select * from Entity where id in (1, null)
    

    可以返回记录,因为如果它找到一个 ID = 1 的元素就知道它在集合中
    请求:

    select * from Entity where (ID not in (1, null))
    

    不能满足,因为空值可以是任意值。

    【讨论】:

    • 解释很好,但NULLNULL,而不是任何值。这是一个特殊值,但绝对不是ANY 值。实际上,对我而言,记住以下内容就足够了:where null = null - 返回 0 行,where null != null - 0 行,null > null - 零行,几乎所有其他以 NULL 作为参数的操作都返回 false我>。所有这些都适用于 IN-operator (因为它基本上与将 == 项目与 ( parentheses - list ) 中的每个元素进行比较几乎相同)。
    【解决方案3】:

    回答

    解决方案已经发布in this answer,我的解决方案也差不多:

    where
      "field" is NOT NULL
      AND "field" not in (1)
    

    不要忘记,条件的反转版本 (is null or in (list)) 使用 OR-运算符(而不是 AND):

    where
      "field" is NULL
      OR "field" in (1)
    

    奖励:SQL 和 NULL

    这是一个优秀的 SQL 开发人员在潜意识中的某个地方(该请求已在 Postgres 中测试过,但我很确定这是标准 ANSI SQL 的行为):

    select
        -- simple things
        1 = 1,              -- true
        1 = 2,              -- false
        -- "simple things" with null
        1  = null,          -- null (and it is not `false` if you expected this)
        1 != null,          -- null (and it is not `true` if you expected this)
        -- "strange" area:
        null  = null,       -- null (and it is not `true` and not `false`)
        null != null,       -- null (and it is not `true` and not `false`)
        1 > null,           -- null (yeah, after 4 previous examples it is exactly what you expected)
        1 < null,           -- null
        null < null,        -- null
        null > null,        -- null
        -- value IN ()
        1 in (1,2),         -- true
        1 in (1,null),      -- true
        1 in (2, 3),        -- false
        1 in (2, null),     -- !!! null
        -- value NOT IN
        1 not in (1,2),     -- false
        1 not in (1,null),  -- false
        1 not in (2, 3),    -- true
        1 not in (2, null), -- !!! null
        -- NULL IN/NOT IN
        null in (1,2),      -- null
        null in (NULL),     -- null
        null not in (1,2),  -- null
        null not in (NULL), -- null
        -- and surprise:
        NOT NULL            -- !! NULL (but most probably you foresaw/knew this)
    
    

    如您所见 - 如果 null 是操作数,则结果为 null 并且在布尔上下文中(例如,在 WHERE 子句中) - 它是 falsey .虽然,falseyfalse 不一样,NOT (1=NULL) 是 NULL,但不是 truly,所以这两个请求都返回 0 行:

    -- 1
    select 1 where (1 = null)
    
    -- 2
    select 1 where NOT (1 = null)
    

    希望对你有用

    【讨论】:

    • =/ 这个链接就在这里?
    • > 链接在这里——是的,那个人首先发布了他的答案,所以我添加了一个链接到他的答案(实际上和我的一样,或者我的和他的一样),我只是添加了一些关于 PG 操作如何处理 NULL 操作数的注释
    【解决方案4】:
    select * 
    from Entity this_ 
    where (this_.ID not in (null))
    

    “IN”或“NOT IN”不选择 NULL 值 你可以写

    select * 
    from Entity this_ 
    where (this_.ID not in (1))
    

    而且您的选择不会包含空值

    【讨论】:

    • 欢迎您!这个答案似乎重复了本页其他地方的答案中已经包含的信息,而不是代表问题的新答案。如果你还没有,你可能想看看tour,它解释了这个网站是如何工作的。
    【解决方案5】:

    我也遇到过类似的in问题,最终想出了以下解决方案;

    select * from public."Employee_11" where (COALESCE("Name",'@'),"Surname") 
        in (
            ('@','dummy')
        )
    

    它确实返回 Name 列具有空值的记录。您也可以将此用于 not in 子句,该子句将返回 Name 的非空记录;

      select * from public."Employee_11" where (COALESCE("Name",'@'),"Surname") 
            not in (
                ('@','dummy')
            )
    

    【讨论】:

      【解决方案6】:

      我有类似的问题。我对 SQL 很了解的自尊心被戳破了。 这是 scott/tiger 表中的简化示例。

      select empno, ename from emp where deptno not in (10, 20, null);
      

      什么也没返回。尽管我非常谨慎地使用 NOT IN 条件,因为它不使用索引并且非常慢。我更喜欢使用 OUTER JOIN 代替。

      我在 Postgres 和 Oracle 中都试过这个查询,结果是一样的。因此,必须是符合标准的结果。 NULL 仅在 NOT IN 条件下才会如此。

      【讨论】:

      • 所有 DBMS 都以这种方式运行。 deptno not in (10, 20, null);detpno &lt;&gt; 10 AND detpno &lt;&gt; 20 AND deptno &lt;&gt; NULL 相同(例如,对于 detpno=1)与 false AND false AND null 相同,而 NULL 又是 WHERE 子句的“不正确”。结果与deptno 的值无关,因此对于表中的所有行它都是“不正确的”,因此它什么也不返回。
      【解决方案7】:

      您可以使用 ANY 运算符。 您的代码示例:

      select 
        * 
      from Entity this_ 
      where 
         (this_.ID <> ANY (null))
      

      【讨论】:

      • 这个行为就像 NOT IN,null 确实返回任何东西。
      猜你喜欢
      • 2013-01-12
      • 2019-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多