mysql not in 查询不出来null的原因
在 MySQL 中使用 NOT IN
进行查询时无法查出 NULL
值,这与 SQL 中 NULL
值的比较规则有关。下面详细解释原因及解决方案。
原因分析
在 SQL 里,NULL
代表未知的值,它与任何值(包括另一个 NULL
值)进行比较的结果都是 UNKNOWN
,而非 TRUE
或 FALSE
。NOT IN
操作本质上是一系列的不等于比较。
例如,有如下查询:
SELECT * FROM table_name WHERE column_name NOT IN (value1, value2, NULL);
这个查询等价于:
SELECT * FROM table_name WHERE (column_name != value1) AND (column_name != value2) AND (column_name != NULL);
由于 column_name != NULL
的结果是 UNKNOWN
,而 WHERE
子句只会返回条件结果为 TRUE
的行,所以包含 NULL
的比较会使整个条件不满足,从而无法查询出 NULL
值。
示例说明
假设有一个 students
表,结构和数据如下:
CREATE TABLE `students` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) DEFAULT NULL,
`score` int(11) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
INSERT INTO `students`(`id`, `name`, `score`) VALUES (1, 'Alice', 80);
INSERT INTO `students`(`id`, `name`, `score`) VALUES (2, 'Bob', NULL);
INSERT INTO `students`(`id`, `name`, `score`) VALUES (3, 'Charlie', 90);
当执行以下 NOT IN
查询时:
SELECT * FROM students WHERE score NOT IN (80, NULL);
因为 score != NULL
的结果是 UNKNOWN
,所以该查询不会返回 score
为 NULL
的行,也不会返回 score
为 80 的行,最终没有符合条件的结果。
解决方案
1. 过滤掉 NULL
值
如果 NOT IN
列表中的 NULL
是不必要的,可以在使用前将其过滤掉。
SELECT * FROM students WHERE score NOT IN (80);
2. 使用 IS NULL
结合 NOT IN
如果 NOT IN
列表中可能存在 NULL
值,并且你想同时处理 NULL
值的情况,可以使用 IS NULL
来明确处理。
SELECT * FROM students WHERE score NOT IN (80) OR score IS NULL;
3. 使用 LEFT JOIN
和 IS NULL
另一种方法是使用 LEFT JOIN
和 IS NULL
来模拟 NOT IN
的效果,同时处理 NULL
值。
SELECT s.*
FROM students s
LEFT JOIN (SELECT 80 AS score) filter ON s.score = filter.score
WHERE filter.score IS NULL;
4. 使用 EXISTS 来模拟 NOT IN 的效果
SELECT stu.* FROM students stu where not EXISTS(select * from students stu1 where stu1.score ='80' and stu.id = stu1.id)