为什么“AND NOT field = 'value'”过滤掉空值?

问题描述

我的查询看起来基本上像

WITH DATA AS(
 SELECT fields
    FROM table
        WHERE [many conditions]
        AND NOT field1 = 'string'           
)

SELECT foo,bar,CASE
        WHEN field1 IS NULL THEN 'other_string'
        [other cases]
    END
FROM data

还有很多其他事情在进行,但这是不起作用的核心部分。这应该给我很多结果。但相反,这种特殊情况的结果为零;如果我删除查询的其余部分并基本上只运行这个,它只是一个空表。

AND NOT field1 = 'string' 似乎过滤掉 field1 为“字符串”的所有行,但同时过滤掉 field1 为空的所有行。如果 field1 为 null,则 field1 = 'string' 应计算为 false(因为 null 不等于任何值),因此 NOT field1 = 'string' 应计算为 true,并且这些行应在查询中 - 对吗?

实际上不确定我正在使用的 Redash 前端后面运行的是什么 sql 实现,但我可以确定它是否相关。

解决方法

几乎所有与 NULL 的比较都会返回 NULL。两个突出的例外是 IS NULLIS NOT NULL,它们返回“true”或“false”。

NULL 的语义非常简单:

  • NOT NULL --> NULL
  • TRUE AND NULL --> NULL
  • FALSE AND NULL --> FALSE
  • TRUE OR NULL --> TRUE
  • FALSE OR NULL --> NULL

如果您将 NULL 视为表示 *unknown" 值而不是 缺失 值,则语义更容易理解。

WHERE 子句仅通过评估为“true”的行。因此,“false”和 NULL 都被删除了。请注意,这与 CASE 表达式相同。但是,CHECK 表达式将 NULL 视为“true”。好吧,从来没有人指责 SQL 的内部一致性。

你的表达是:

WHERE [many conditions] AND NOT field1 = 'string'    

field1NULL 时:

WHERE [many conditions] AND NOT (NULL = 'string')
WHERE [many conditions] AND NOT (NULL)
WHERE [many conditions] AND NULL
WHERE NULL

非常简单的逻辑。

注意:标准 SQL 有一个 NULL 安全比较器,即:

WHERE [many conditions] AND field1 IS DISTINCT FROM 'string'

某些数据库为此使用 <=>

WHERE [many conditions] AND NOT field1 <=>'string'

在其他情况下,您需要更加明确:

WHERE [many conditions] AND (field1 <> 'string' OR field1 IS NULL)
,

如果将 NULL 与 SQL 中的另一个值进行比较,结果将为 NULL。但是当您使用 IS NULLIS NOT NULL 进行显式比较时,将相应地考虑 NULL 值。

所以你的情况应该是

(NOT (field1 = 'string') OR field1 IS NULL)

或者更易读一点(<> 表示不等于):

(field1 <> 'string' OR field1 IS NULL)

Here 您可以找到有关 SQL NULL 值的一些详细信息。

无法使用比较运算符(例如 =、)测试 NULL 值。 我们将不得不改用 IS NULL 和 IS NOT NULL 运算符。