当前位置: 首页 > news >正文

SQL LEFT JOIN 与 WHERE 条件的隐藏坑

在日常开发中,我们经常用 LEFT JOIN 来保留左表数据,即使右表没有匹配记录也能查到结果。然而,如果不小心把右表的过滤条件写在了 WHERE 子句里,就会让 LEFT JOIN 失效,变成了“变相 INNER JOIN”。

本文通过一个真实案例,分析这个坑的成因、表现和正确写法。


1. 场景背景

我在调试一个查询时,遇到一个很奇怪的现象:

  • 单独查右表子查询是有数据的
  • 但是和左表 LEFT JOIN 之后,结果却是空的

SQL 如下:

SELECTb.project_code,b.account_code,b.group_code,b.group_name,p.finish_date,p.actual_finish_date,p.job_code
FROM (-- 楼栋表,按项目、账户、组团去重SELECT DISTINCTproject_code,account_code,group_code,group_nameFROM t_jsc_ysjgzj_building_account WHERE batch_number = (SELECT max(batch_number) FROM t_jsc_ysjgzj_building_account)AND delete_flag = 0AND group_code IS NOT NULL AND group_code != ''AND account_code = '0200096829000128958'
) b
LEFT JOIN t_jh_all_plan_list_detail pON b.group_code = p.gr_id
WHERE p.delete_flag = 0AND p.is_ignored = 0AND p.job_code IN ('JT00056', 'JT00019');

2. 问题原因

很多人误以为 LEFT JOIN 后写任何条件都能保留左表数据,其实不然。
右表无匹配行 时,右表的所有列都是 NULL

  • 条件 p.delete_flag = 0 等价于 NULL = 0,结果是 FALSE
  • 条件 p.job_code IN (...) 等价于 NULL IN (...),结果也是 FALSE

于是,这些记录在 WHERE 阶段被过滤掉,相当于把 LEFT JOIN 转成了 INNER JOIN


3. 直观对比

写法位置右表无匹配行时左表数据是否保留
条件写在 ON条件判断发生在匹配阶段,右表为 NULL 依然保留左表✅ 保留
条件写在 WHERE条件判断在匹配后过滤阶段,右表 NULL 导致条件不成立❌ 不保留

4. 正确写法

将对右表的过滤条件移动到 ON 子句中:

SELECTb.project_code,b.account_code,b.group_code,b.group_name,p.finish_date,p.actual_finish_date,p.job_code
FROM (SELECT DISTINCTproject_code,account_code,group_code,group_nameFROM t_jsc_ysjgzj_building_account WHERE batch_number = (SELECT max(batch_number) FROM t_jsc_ysjgzj_building_account)AND delete_flag = 0AND group_code IS NOT NULL AND group_code != ''AND account_code = '0200096829000128958'
) b
LEFT JOIN t_jh_all_plan_list_detail pON b.group_code = p.gr_idAND p.delete_flag = 0AND p.is_ignored = 0AND p.job_code IN ('JT00056', 'JT00019');

这样做的好处:

  • 保证了 LEFT JOIN 的“左表优先保留”特性
  • 避免了无匹配数据被误删

5. 总结

  • LEFT JOIN 条件要分清位置

    • 右表条件 → 写在 ON(保留左表数据)
    • 左表条件 → 写在 WHERE(正常过滤)
  • 检查 SQL 结果异常时

    • 看右表字段是否在 WHERE 中被硬性约束
    • 如果是,就考虑挪到 ON
  • 口诀

    LEFT JOIN 不生效,
    多半 WHERE 害的。
    条件放在 ON,
    左表才安全。
    ``
http://www.dtcms.com/a/331143.html

相关文章:

  • anaconda创建pytorch1.10.0和pytorch2.0.0的GPU环境
  • iOS 26 一键登录失效:三大运营商 SDK 无法正常获取手机号
  • 装个 Oracle 23ai 本地版玩玩~
  • 短剧小程序系统开发:赋能创作者,推动短剧艺术创新发展
  • SpringBoot+Vue线上部署MySQL问题解决
  • CPP模板编程
  • AI驱动的智能爬虫架构与应用
  • openvsx搭建私有插件仓库
  • 设计模式有哪些
  • 2022_ISG_CTF-rechall详解(含思考过程)
  • MixOne在macOS上安装碰到的问题
  • 上网行为安全概述
  • 【跨越 6G 安全、防御与智能协作:从APT检测到多模态通信再到AI代理语言革命】
  • 数据结构:用链表实现队列(Implementing Queue Using List)
  • python批量爬虫实战之windows主题爬取
  • 移位操作符技巧
  • 8. 函数简介
  • DeepSeek补全IBM MQ 9.4 REST API 执行命令的PPT
  • Mac chrome浏览器下载DevEco Studio 6.0.0 Beta2失败
  • 分布式锁—Redisson的公平锁
  • 线上故障定位:从报警到根因的实战指南
  • Eureka故障处理大汇总
  • 使用 Git Submodules 管理前后端分离项目
  • scikit-learn/sklearn学习|广义线性回归 Logistic regression的三种成本函数
  • Docker 核心技术:Namespace
  • Java毕业设计选题推荐 |基于SpringBoot的健身爱好线上互动与打卡社交平台系统 互动打卡小程序系统
  • 2019 GPT2原文 Language Models are Unsupervised Multitask Learners - Reading Notes
  • [激光原理与应用-274]:理论 - 波动光学 - 光是电磁波,无线电磁波可以通过天线接收和发送,为什么可见光不可以?
  • Visual Studio2019/2022离线安装完整教程(含闪退解决方法)
  • 无人机双目视觉设计要点概述!