PostgreSQL中LEFT JOIN与单表查询的NULL值过滤逻辑疑问
PostgreSQL单表查询与LEFT JOIN查询的NULL过滤逻辑是否有差异?
PostgreSQL对NULL值的过滤逻辑在单表查询和含LEFT JOIN的复杂查询中完全一致,不存在差异。核心原因在于SQL中NULL值的比较规则是统一的:
- 任何与NULL的比较操作(包括
!=、=、<等)返回的结果既不是TRUE也不是FALSE,而是NULL。 - WHERE子句只会保留条件结果为TRUE的行,结果为NULL或FALSE的行都会被过滤掉。
你的查询分析
- 带LEFT JOIN的初始查询
SELECT * FROM feed_common LEFT JOIN user_message_query ON feed_common.id = user_message_query.feed_common_id WHERE user_message_query.user_message_outbox_id IS NULL AND feed_common.verification_status != 'spam'
这里的feed_common.verification_status != 'spam'条件,当verification_status为NULL时,比较结果是NULL,不符合WHERE子句要求的TRUE,所以这类行被过滤,和LEFT JOIN本身无关。
- 单表查询
SELECT * FROM feed_common WHERE feed_common.verification_status != 'spam'
这个条件的逻辑和上面完全相同,verification_status为NULL的行同样会被过滤,你之前误以为会返回是误读了结果。
- 修改后的有效查询
SELECT * FROM feed_common LEFT JOIN user_message_query ON feed_common.id = user_message_query.feed_common_id WHERE user_message_query.user_message_outbox_id IS NULL AND ( feed_common.verification_status != 'spam' OR feed_common.verification_status IS NULL)
这里通过OR feed_common.verification_status IS NULL明确把NULL的情况纳入条件,此时verification_status为NULL的行,整个括号内的条件结果为TRUE,所以会被保留下来。
总结
不管是单表还是多表JOIN查询,PostgreSQL处理NULL比较的规则都是统一的:NULL参与比较返回NULL,WHERE只留TRUE的行。你遇到的差异是误解了单表查询的结果,而非PostgreSQL对不同查询类型的处理逻辑有区别。
内容的提问来源于stack exchange,提问作者Maanas B
相关产品推荐
相关产品推荐

