NOT IN 的 NULL 陷阱:一次 UNION 数据“神秘消失“

昨天写了个 SQL,逻辑明明没毛病,数据就是查不出来。排查半天,元凶竟是 NULL

一、现象:我的数据呢?

先看我写的 SQL,很简单:

SQL 复制代码
WITH tmp_union3 AS (
    SELECT * FROM tmp_union
    UNION ALL
    SELECT * FROM tmp_union2
    WHERE id NOT IN (
        SELECT DISTINCT id FROM tmp_union
    )
)
SELECT * FROM tmp_union3 WHERE id = '23009724';

已知:

  • tmp_union 里没有 '23009724'
  • tmp_union2明明有 '23009724'

按道理,NOT IN 应该放行,然后 UNION ALL 合并,最后查出来。

结果:查无此记录。

二、排查:问题出在哪?

先单独跑 NOT IN 这一段:

SQL 复制代码
SELECT * FROM tmp_union2
WHERE id NOT IN (SELECT DISTINCT id FROM tmp_union);

返回:空结果集

'23009724' 明明不在 tmp_union 里,凭啥被过滤了?

再查一下 tmp_union 的数据:

SQL 复制代码
SELECT id FROM tmp_union;

破案了------tmp_union 里有 NULL

三、原理:一个 NULL,全军覆没

在 PostgreSQL 里,没有unknown,只有null,NULL 代表"未知"

NOT IN 的右侧出现 NULL 时:

SQL 复制代码
'2026' NOT IN (NULL, '2025', '2026')

数据库实际比较:

SQL 复制代码
'2026' = '2025'  → FALSE
'2026' = NULL        → NULL   -- 不是 FALSE,是 NULL!

关键点来了:

NOT IN 的本质是 AND 串联的等值比较

Plain 复制代码
'2026' <> NULL AND '2026' <> '2025' AND ...

在 PG 里,NULL AND FALSE 的结果是 NULLNULL AND TRUE 也是 NULL

WHERE 子句只认 TRUENULL 被当成不满足条件。

所以只要 NOT IN 的右侧集合里有一个 NULL,整个条件就塌了,所有行都被过滤。

不是一个,是全部。这就是黑洞。

四、修复:三选一

方法 1:过滤 NULL(改动最小)

SQL 复制代码
WHERE id NOT IN (
    SELECT DISTINCT id FROM tmp_union
    WHERE id IS NOT NULL  -- 加这一行
)

方法 2:改用 NOT EXISTS(推荐)

SQL 复制代码
SELECT * FROM tmp_union2 t2
WHERE NOT EXISTS (
    SELECT 1 FROM tmp_union t1
    WHERE t1.id = t2.id
);

NOT EXISTS 不受 NULL 影响,而且性能通常更好。

方法 3:LEFT JOIN 取差集

SQL 复制代码
SELECT t2.*
FROM tmp_union2 t2
LEFT JOIN tmp_union t1 ON t1.id = t2.id
WHERE t1.id IS NULL;

五、口诀

看到NOT IN,先防NULL;能写EXISTS,别写IN

六、总结

这次踩坑就一句话:

NOT IN 遇到 NULL,不是漏几条,是全部消失。

而且不会报错,悄无声息。

你以为是逻辑问题,其实是 NULL 在搞鬼。

以后写 SQL,遇到 NOT IN 多长个心眼,或者直接换成 NOT EXISTS,一劳永逸。

你遇到过类似的 NULL 陷阱吗?评论区聊聊,一起排雷。

相关推荐
覆东流6 小时前
7.Java数组
java·开发语言·后端
码行山野赴时序归途6 小时前
三道经典数组题:从暴力到最优的算法思维
c语言·开发语言·数据结构·算法·leetcode
lzhdim6 小时前
提高 SQL 语句执行速度的方法
java·开发语言·数据库·sql·oracle
JavaPub-rodert6 小时前
王仕宇在 Go Context 如何解决协程泄漏与超时控制
开发语言·后端·golang·iphone·javapub·王仕宇
ly76898 小时前
JavaScript 从入门到进阶:核心语法、异步编程与工程化实践
开发语言·javascript·ecmascript
落魄大学生之流水线上谋生计8 小时前
Java锁全面指南:从基础概念到企业级应用
java·开发语言
for_ever_love__8 小时前
python基础语法学习: 闭包
开发语言·python·学习·闭包
ly76898 小时前
Python 全面入门:从核心语法到工程实践
开发语言·python
Faith_xzc9 小时前
一条 SQL 顶一条 Flink 链路?Doris Streaming Job 持续导入全景解析
大数据·数据库·sql·flink
爱学习的小白柏9 小时前
【AI问数技术】多Agent协同架构:查询规划/SQL生成/洞察分析/报告生成
java·网络·人工智能·windows·sql·架构·llama