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

Why is "AND NOT field = 'value'" filtering out nulls?

我的查询基本上像

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

还有很多其他事情正在发生,但这是不起作用的核心部分。 应该给我很多结果。但相反,该特定案例的结果为零;如果我删除查询的其余部分并且 运行 基本上就是这个,它只是一个空的 table.

AND NOT field1 = 'string' 似乎过滤掉了 field1 为 'string' 的所有行,但也过滤掉了 field1 为空的所有行。如果 field1 为 null,那么 field1 = 'string' 应该评估为 false(因为 null 不等于任何东西)因此 NOT field1 = 'string' 应该评估为 true 并且这些行应该在查询中 - 对吧?

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

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

所以你的情况应该是

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

或者可能更具可读性(<> 表示不等于):

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

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

It is not possible to test for NULL values with comparison operators, such as =, <, or <>. We will have to use the IS NULL and IS NOT NULL operators instead.

几乎所有与NULLreturns NULL的比较。两个突出的例外是 IS NULLIS NOT NULL,其中 return 要么是“真”要么是“假”。

NULL 具有非常简单的语义:

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

如果您认为 NULL 代表一个 *unknown" 值而不是 missing 值,那么语义更容易理解。

A WHERE 子句只传递计算结果为“真”的行。因此,“false”和 NULL 都被删除了。请注意,这与 CASE 表达式相同。但是,CHECK 表达式将 NULL 视为“真”。嗯,没有人指责 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)