SQL中JOIN的ON条件不匹配NULL值,因NULL比较结果为UNKNOWN而非TRUE;INNER JOIN会跳过含NULL的行,外连接仅保留但不匹配NULL;需用OR、COALESCE或IS NOT DISTINCT FROM显式处理NULL相等。
SQL 中 JOIN 的 ON 条件对 NULL 值**不进行匹配**——这是核心规则。因为 NULL 表示“未知”,而任何与 NULL 的等值比较(如 col1 = col2)结果都不是 TRUE,而是 UNKNOWN;而 JOIN 只保留条件评估为 TRUE 的行,UNKNOWN 被当作不匹配处理。
如果连接列中任一值为 NULL,该行不会出现在 INNER JOIN 结果中。
t1.id = 1, t1.code = NULL 与 t2.id = 1, t2.code = NULL —— 尽管都为 NULL,但 NULL = NULL 返回 UNKNOWN,不满足 JOIN 条件,因此无匹配。LEFT/RIGHT/FULL OUTER JOIN 的作用是**保留某侧或两侧的所有行**,包括那些本该因无匹配而丢失的 NULL 行,但它本身并不改变 NULL 的比较逻辑。
LEFT JOIN ... ON t1.a = t2.b:t1 中 a IS NULL 的行仍会出现在结果里,但对应 t2 列全为 NULL(表示未找到匹配),并非因为 NULL 和 NULL 匹配成功。数据库不会默认把两个 NULL 当作相同值来连,必须显式声明这种意图。常用方法有:
ON (t1.col = t2.col) OR (t1.col IS NULL AND t2.col IS NULL)
ON COALESCE(t1.col, '>') = COALESCE(t2.col, '>')
ON t1.col IS NOT DISTINCT FROM t2.col —— 这是语义上最准确的 NULL 安全比较。有人试图用 WHERE t1.col = t2.col OR (t1.col IS NULL AND t2.col IS NULL) 替代 ON 条件,这是错误的。WHERE 是在 JOIN 完成后过滤结果,此时 INNER JOIN 已经丢弃了所有含 NULL 的潜在匹配行,WHERE 再怎么写也找不回来。逻辑必须放在 ON 中。