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

主题:SQL 中 NOT EXISTS 的原理与最佳实践

两个sql,在某些情况下执行结果是一样的(not in如果子查询为null,可以直接报错)

---未上报的企业 select oewrt.id, oewrt.COUNTY_ID, oewrt.ENT_NAME, oewrt.LINKMAN, oewrt.PHONE from OIL_ENTER_WHSLEWHSE_RECORD_TAB oewrt where id not in (select oewrt.id from OIL_ENTER_MONTH_REPORT oemr left outer join OIL_ENTER_WHSLEWHSE_RECORD_TAB oewrt ON oewrt.id = oemr.RECORD_ID AND oemr.MONTH = :MONTH where oewrt.COUNTY_ID like substr(:countyId, 1, 2) || '%' and oewrt.ENT_TYPE IN (:ENT_TYPE, '3') AND oewrt.CONFIRM_STATUS = '2') and oewrt.COUNTY_ID like substr(:countyId, 1, 2) || '%' and oewrt.ENT_TYPE IN (:ENT_TYPE, '3') AND oewrt.CONFIRM_STATUS = '2';

而not exists更加安全,为什么?

SELECT oewrt.id, oewrt.COUNTY_ID, oewrt.ENT_NAME, oewrt.LINKMAN, oewrt.PHONE FROM OIL_ENTER_WHSLEWHSE_RECORD_TAB oewrt WHERE NOT EXISTS ( SELECT 1 FROM OIL_ENTER_MONTH_REPORT oemr WHERE oemr.RECORD_ID = oewrt.id AND oemr.MONTH = :MONTH ) and oewrt.COUNTY_ID LIKE SUBSTR(:countyId, 1, 2) || '%' AND oewrt.ENT_TYPE IN (:ENT_TYPE, '3') AND oewrt.CONFIRM_STATUS = '2';

❓ 你可能在想:

“如果子查询只写SELECT 1,那数据库怎么知道该排除主表中的哪一行?它连要比较的字段都没返回啊!”

答案是:比较字段不在SELECT里,而在WHERE里!


✅ 核心原理:关联条件在WHERE,不在SELECT

看这个经典写法:

SELECT * FROM customers c WHERE NOT EXISTS ( SELECT 1 -- ← 这里只表示“有结果就行” FROM orders o WHERE o.customer_id = c.id -- ← 关键在这里!建立关联 AND o.month = '202506' );

🔍 执行过程(对主表每一行):

  1. 拿到当前客户c.id = 1001
  2. 执行子查询:
    SELECT 1 FROM orders WHERE customer_id = 1001 AND month = '202506'
  3. 数据库去orders表里找:
    • 有没有一行满足customer_id = 1001month = '202506'
  4. 如果→ 子查询返回至少一行 →NOT EXISTS = false不选这个客户
  5. 如果没有→ 子查询返回空 →NOT EXISTS = true选中这个客户

🎯关键:关联字段c.ido.customer_id是通过WHERE o.customer_id = c.id建立的,和SELECT 1完全无关!


🧠 类比理解

想象你在查“没交作业的学生”:

  • 主表:全班学生名单(张三、李四、王五)
  • 子表:作业提交记录(张三、李四)

你不需要从作业记录里“返回学生名字”来对比,而是这样操作:

对每个学生,去作业记录里“按名字查找”

  • 能找到 → 交了 → 排除
  • 找不到 → 没交 → 保留

这里的“按名字查找”就是WHERE o.customer_id = c.id
SELECT 1只是回答:“找到了吗?(是/否)”


❌ 为什么你会觉得“需要返回字段”?

可能是因为混淆了以下两种模式:

模式写法依赖返回值?
集合排除WHERE id NOT IN (SELECT customer_id FROM ...)✅ 需要子查询返回具体值
存在性检查WHERE NOT EXISTS (SELECT 1 FROM ... WHERE 关联条件)❌ 不需要返回值,只看是否有行
  • NOT IN确实需要子查询返回一个值列表,然后主查询用这个列表做排除。
  • NOT EXISTS完全不依赖返回值,它只关心子查询是否能“找到匹配行”。
📌关键词 / 线索区(Cue Column)
  • NOT EXISTSvsNOT IN
  • 存在性检查(Existence Check)
  • 关联条件位置
  • 为什么用SELECT 1
  • NULL 安全性
  • 执行逻辑:逐行验证
  • 性能与可读性

📖主笔记区(Notes)

1. 核心思想
NOT EXISTS不是通过“返回字段值”来排除数据,而是对主表每一行,在子表中检查是否存在匹配记录。只要子查询返回 ≥1 行,EXISTS = true;否则为false

2. 关联靠WHERE,不靠SELECT

  • 关键关联写在子查询的WHERE中,例如:
    WHERE oemr.RECORD_ID = oewrt.id AND oemr.MONTH = :MONTH
  • SELECT 1只是一个占位符,表示“只关心是否有结果”,不参与逻辑判断。

3. 为什么用SELECT 1

  • ✅ 语义清晰:表明仅做存在性检查
  • ✅ 性能略优:避免读取实际列数据(尤其在旧数据库)
  • ✅ 行业惯例:被广泛接受的最佳实践

4.NOT EXISTSvsNOT IN

对比项NOT EXISTSNOT IN
工作方式逐行验证是否存在排除一个值列表
NULL 安全✅ 安全(不受影响)❌ 危险(含 NULL 则结果为空)
性能通常更快(可短路)可能全表扫描
可读性逻辑清晰易误解

5. 执行过程(伪代码)

for each row in 主表: if 子查询(带当前行的关联值) 返回 ≥1 行: 跳过(不满足 NOT EXISTS) else: 保留该行

6. 典型应用场景

  • 查询“未下单的客户”
  • 查找“未提交月报的企业”
  • 检测“缺少某类记录的数据”

🔚总结区(Summary)

NOT EXISTS是 SQL 中进行“不存在”判断的安全、高效、清晰的方式。它通过在子查询的WHERE子句中建立与主表的关联,逐行验证是否存在匹配记录,而SELECT 1仅作为存在性信号,不参与实际筛选。相比NOT IN,它天然规避了 NULL 带来的逻辑陷阱,是生产环境中推荐的标准写法。

💡口诀
关联写在 WHERE 里,SELECT 1 只问有没有;
逐行验证最可靠,NULL 再也不犯愁。


建议行动

  • 在今后写“未上报”“未完成”“无记录”类查询时,优先使用NOT EXISTS + SELECT 1
  • 避免在可能含 NULL 的场景使用NOT IN
  • 为子表的关联字段(如RECORD_ID, MONTH)建立复合索引以提升性能
http://www.cnnetsun.cn/news/126853.html

相关文章:

  • 企业合同管理的安全锁——合同系统智能化
  • 光速革命:Diffractive-Deep-Neural-Networks开启光子AI新纪元
  • 高效自动化网络管理:Kea DHCP完整解决方案实战指南
  • 纯电动汽车两档ATM变速箱Simulink模型:含换挡控制与执行模块,附详细文档与注释
  • WebToEpub终极指南:一键将网页小说变电子书
  • 终极指南:escrcpy实现手机息屏远程控制的完整教程
  • Office.js 终极入门指南:快速开发你的第一个Office插件
  • AMD驱动精简终极指南:快速上手Radeon Software Slimmer
  • SpiffWorkflow工作流引擎实战:精通Python BPMN自动化
  • Unlock Music音乐解锁神器:打破数字限制,重获音乐自由
  • 5分钟掌握TinyVT:Windows系统监控的终极隐身术
  • Blender MMD工具完全指南:从模型导入到动画制作
  • MCP续证如何高效备考?(资深讲师亲授通关秘籍)
  • 复旦最新一篇DriveVGGT:面向自动驾驶,高效实现多相机4D重建
  • Dart Simple Live终极指南:一站式跨平台直播聚合解决方案
  • 3步解锁网易云NCM加密:ncmdumpGUI完全操作手册
  • 息屏远程控制终极指南:让escrcpy成为你的手机隐形管家
  • Happy Holidays from atsec
  • 办公室中的Python课 P07 【逻辑大脑】条件判断:让你的代码学会“做决定”
  • AI Agent部署权限设计(高阶安全架构全公开)
  • GIF流畅度提升终极指南:Waifu2x完整使用教程
  • MCP续证倒计时:5天内完成考试预约的紧急操作手册(限时必读)
  • MCP SC-400量子加密实战,你必须掌握的7个关键技术点
  • 终极DMG文件转换指南:免费开源工具DMG2IMG完整教程
  • 【MCP量子认证模拟试题全揭秘】:掌握这10道高频题,轻松通过考试
  • WinPython碰撞系统优化终极指南:打造流畅的射击游戏体验
  • 揭秘AZ-500云Agent故障恢复全流程:3步实现99.9%可用性保障
  • MAUI条码扫描终极指南:快速集成专业级扫码功能
  • 1、高效调试:.NET 与 Windows 应用开发的关键
  • 智慧农业技术与装备专业产教协同育人解决方案