news 2026/2/27 16:34:35

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
主题: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)建立复合索引以提升性能
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/26 19:04:23

企业合同管理的安全锁——合同系统智能化

合同系统智能化,为企业合同管理上把安全锁一、引言在当今数字化时代,企业的合同管理面临着诸多挑战。合同数量庞大、流程繁琐、风险难以把控等问题,都可能给企业带来潜在的损失。而合同系统智能化的出现,为企业合同管理提供了新的…

作者头像 李华
网站建设 2026/2/23 3:36:40

光速革命:Diffractive-Deep-Neural-Networks开启光子AI新纪元

光速革命:Diffractive-Deep-Neural-Networks开启光子AI新纪元 【免费下载链接】Diffractive-Deep-Neural-Networks Diffraction Deep Neural Networks(D2NN) 项目地址: https://gitcode.com/gh_mirrors/di/Diffractive-Deep-Neural-Networks Diffractive-Dee…

作者头像 李华
网站建设 2026/2/25 9:09:54

高效自动化网络管理:Kea DHCP完整解决方案实战指南

高效自动化网络管理:Kea DHCP完整解决方案实战指南 【免费下载链接】kea A modern, scalable, robust DHCPv4 and DHCPv6 server, with database (MySQL, PostgreSQL), hooks, multi-threading, RADIUS, NETCONF, Kerberos and more. 项目地址: https://gitcode.c…

作者头像 李华
网站建设 2026/2/25 17:38:24

WebToEpub终极指南:一键将网页小说变电子书

WebToEpub终极指南:一键将网页小说变电子书 【免费下载链接】WebToEpub A simple Chrome (and Firefox) Extension that converts Web Novels (and other web pages) into an EPUB. 项目地址: https://gitcode.com/gh_mirrors/we/WebToEpub 你是否曾在网络信…

作者头像 李华
网站建设 2026/2/24 15:26:30

终极指南:escrcpy实现手机息屏远程控制的完整教程

终极指南:escrcpy实现手机息屏远程控制的完整教程 【免费下载链接】escrcpy 优雅而强大的跨平台 Android 设备控制工具,基于 Scrcpy 的 Electron 应用,支持无线连接和多设备管理,让您的电脑成为 Android 的完美伴侣。 项目地址: https://gitcode.com/v…

作者头像 李华