问题描述
我的查询看起来基本上像
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 NULL
和 IS 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'
当 field1
为 NULL
时:
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 NULL
或 IS 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 运算符。