首页/数据/SQL 速查/连接键为 NULL 的行不会匹配

连接键为 NULL 的行不会匹配

NULL 与其他任何值(包括 NULL)比较都是 UNKNOWN:连接键含 NULL 的行在内连接中直接消失,在左连接中保留但补 NULL。

SQL 速查数据更新于 2026-10-13

连接键为 NULL 会怎样

NULL 与任何值比较的结果都是 UNKNOWN,而不是 TRUE,NULL = NULL 同样不成立——因为每个 NULL 表示「未知」,两个未知不能认定为同一个值。后果很直接:连接键含 NULL 的行在内连接里直接消失,在左连接里左表行保留、右表列补 NULL,而且怎么都配不上。「关联数据莫名少了一大部分」这类问题,绝大多数源头就是连接键为空。

基本信息

内连接NULL 键的行被丢弃,不再出现在结果中
左连接左表 NULL 键行保留,右表列全部补 NULL
判空写法必须用 IS NULL / IS NOT NULL,写 = NULL 永远为 UNKNOWN
NULL 安全匹配MySQL 用 <=>;PostgreSQL 用 IS NOT DISTINCT FROM
设计建议连接键尽量设为 NOT NULL,或用统一的哨兵值表示未知

典型使用场景

  • 排查关联结果行数比预期少:先统计连接键的 NULL 比例
  • 左连接后统计子表数据:注意 COUNT(*) 与 COUNT(子表主键) 的口径差异
  • 反连接查询:NULL 键行会被误判成「右表不存在」,需要额外排除
  • 表设计评审:决定连接键是否允许为 NULL、是否使用哨兵值
  • 数据清洗:把无法归属的外键补上默认维度行,再保证连接结果完整

两种连接的行为差异

两种连接的行为差异
-- 内连接:a.k 为 NULL 的行不会出现在结果里
SELECT a.id, b.name
FROM a JOIN b ON a.k = b.k;

-- 左连接:NULL 键行保留,右表列补 NULL
SELECT a.id, b.name
FROM a LEFT JOIN b ON a.k = b.k;

-- MySQL 的 NULL 安全等值:NULL 与 NULL 视为相同
SELECT a.id, b.id
FROM a JOIN b ON a.k <=> b.k;

PostgreSQL 写法与反连接

PostgreSQL 写法与反连接
-- PostgreSQL 没有 <=>,改用 IS NOT DISTINCT FROM
SELECT a.id, b.id
FROM a JOIN b ON a.k IS NOT DISTINCT FROM b.k;

-- 反连接:必须显式排除 NULL 键行,否则它们会被算成「右表不存在」
SELECT a.id
FROM a LEFT JOIN b ON a.k = b.k
WHERE b.k IS NULL AND a.k IS NOT NULL;

NULL 比较三值逻辑

表达式结果说明
NULL = NULLUNKNOWN不是 TRUE,WHERE 中该行被丢弃
NULL <> 1UNKNOWN取 NOT 之后仍是 UNKNOWN
a.k <=> b.kTRUE / FALSEMySQL 的 NULL 安全等值
a.k IS NULLTRUE / FALSE判断空值的唯一正确写法
左连接后统计子表行数要用 COUNT(子表主键) 而不是 COUNT(*):后者会把没匹配上的补 NULL 行也算成 1,指标会明显虚高。
左连接后补 NULL 的行还会连带影响过滤:想限制「右表满足某条件」时必须把条件写在 ON 里,写到 WHERE 会把补 NULL 的行一起筛掉,左连接退化成内连接。
两边都用 NULL 表示「未知归属」,连接关系永远对不上。先做数据归一化(补哨兵值或补一条默认维度行),再谈查询优化,否则只是把问题藏起来。

易错点

  • 内连接结果比预期少,排查很久才发现连接键里有大量 NULL
  • 左连接后用 COUNT(*) 统计子表数据,把无匹配行也计入,报表指标虚高
  • 反连接(LEFT JOIN 后判右表为空)把 NULL 键行当成「不存在」,混入本不该出现的行
  • 用 NULL 安全等值去「修好」连接,掩盖了本该暴露的数据缺失问题

数据来源与参考

  • MySQL 8.0 Reference Manual · Working with NULL Values
  • PostgreSQL Documentation · Null Values
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌