提问人:Manngo 提问时间:3/6/2023 更新时间:3/6/2023 访问量:73
SQL 和 NOT IN 与 NULL
SQL and NOT IN with NULLs
问:
我实际上正在尝试一些与子查询类似的事情,并且无法理解出了什么问题。我设法将问题简化为以下内容。
我有一个简单的表格,其中一列可能包括:NULL
DROP TABLE IF EXISTS data;
CREATE TEMP TABLE data (
id INT PRIMARY KEY,
number INT,
string TEXT
);
INSERT INTO data(id,number,string)
VALUES (1,1,'Apple'),(2,1,'Accordion'),(3,2,'Banana'),(4,2,'Banjo'),(5,NULL,'Whatever');
SELECT * FROM data WHERE number IN(1,2,NULL);
SELECT * FROM data WHERE number NOT IN(1,2,NULL);
https://dbfiddle.uk/KhTzbX_E 上有一个实时版本。
当我查找与列匹配的行时:number
SELECT * FROM data WHERE number IN(1,2,NULL);
正如预期的那样,我得到了一些结果。这不包括 where is 的行,但我认为该表达式是 的缩写。number
NULL
IN
WHERE a = b
如果我寻找不匹配项:
SELECT * FROM data WHERE number NOT IN(1,2,NULL);
我什么也没得到。
我看不出这怎么可能是正确的。表达式必须返回一个有效的列表,否则第一个列表将不起作用。IN(1,2,NULL)
这是怎么回事,有没有正确的方法可以做到这一点?
注意:我知道放入 是愚蠢的,但这个想法是该列表应该是一个可能返回 vew s 的子查询。我也知道我可以过滤掉子查询中的 s。但是,这对我来说似乎是一种解决方法。NULL
NULL
NULL
我已经在PostgreSQL,MariaDB和Microsoft SQL Server中尝试过。
答:
任何涉及 NULL 的相等性检查都将返回 null,并且 null 不等于 null。Null 需要特殊语言使用is/is not
我的建议是在你的 where 子句中添加另一部分以使其工作,并保持其可读性:
SELECT * FROM data WHERE (number NOT IN(1,2) and number is not null);
SELECT * FROM data WHERE (number IN (1,2) or number is null);
尝试使用 null,你会看到它的行为方式:
select case when null = null then 1 else 0 end as test
IN()
是一条捷径。 等同于:number IN(1,2,NULL)
(数字 = 1 或数字 = 2 或数字 = NULL)
不能对必须改用的 NULL 使用相等性,因此 IN 快捷方式将无法按预期使用 NULL 工作。IS NULL
如你所建议的,如果使用子查询,建议你去掉任何 NULL。
基本上,如果涉及任何值,则使用非常有限。这并不是一个新见解。看:NOT IN
null
nr NOT IN (1,2,NULL)
翻译为:
NOT (nr = 1 OR nr = 2 or nr = null)
nr = null
总是 ,并且由于结果 ,表达式永远不会成为 。在子句中使用时,这样的过滤器永远不能返回任何行。null
false OR null
null
true
WHERE
评论
对于没有 NULL 经验的人来说,这是一个古老的陷阱:如果列表包含 NULL,则结果集始终为空。NOT IN
为了理解原因,让我们重写
WHERE number NOT IN (1, 2, NULL)
到语义上等价的
WHERE number <> 1 AND number <> 2 AND number <> NULL
然后请注意,将始终返回 NULL。如果您将“NULL”视为“未知”,则最容易理解:当被问及未知数是否与任何给定数字不同时,答案可能是“true”或“false”,具体取决于未知数的未知值。因此,答案必须是“未知”,即值 NULL。number <> NULL
boolean
现在可以是 (if is ) 或 NULL (if is NULL 或 ),但它永远不可能是 。条件仅传递条件为 的行。和 NULL 都不会通过。something AND NULL
FALSE
something
FALSE
something
TRUE
TRUE
WHERE
TRUE
FALSE
评论
NULL
评论