PostgreSQL中仅当两表字段均非空时JOIN的疑问
为什么PostgreSQL的JOIN会自动过滤关联字段均为NULL的行?
你观察得特别准!这背后的核心原因正是PostgreSQL中NULL不等于NULL——更准确地说,是SQL标准里对NULL的逻辑定义导致的。
1. SQL中NULL的本质:未知值
在SQL体系里,NULL代表的是“未知的、不确定的值”。当你用=比较两个NULL时,结果既不是TRUE也不是FALSE,而是UNKNOWN(第三种逻辑状态)。
而JOIN操作的ON条件只有在结果为TRUE的时候,才会将两张表的行关联起来。如果条件结果是UNKNOWN或者FALSE,这组行就会被排除在结果集之外。
所以你执行的查询:
SELECT * FROM aTable a JOIN bTable b on a.value=b.value;
当a.value和b.value同时为NULL时,a.value=b.value的结果是UNKNOWN,不满足JOIN的匹配要求,自然不会出现在查询结果里。
2. 如果想让NULL也能匹配怎么办?
如果你希望把两个NULL视为相等的情况进行关联,可以使用PostgreSQL支持的IS NOT DISTINCT FROM操作符,它会把NULL和NULL视为相等:
SELECT * FROM aTable a JOIN bTable b on a.value IS NOT DISTINCT FROM b.value;
这样,关联字段均为NULL的行就会被正常关联并返回了。
总结
默认的等值比较(=)对NULL无效,因为NULL之间的比较结果是UNKNOWN,无法满足JOIN的匹配条件。这就是你的查询自动过滤掉这类行的原因。
内容的提问来源于stack exchange,提问作者Richard




