SQL 如何用子查询实现反查询?
发布时间 - 2026-01-26 00:00:00 点击率:次反查询是查不在某集合里的记录,应优先用NOT EXISTS替代WHERE NOT IN以避免NULL导致结果为空;也可用LEFT JOIN+IS NULL实现,但需确保关联字段有索引且正确判空。
什么是反查询:用 NOT EXISTS 替代 WHERE NOT IN
反查询本质是“查不在某集合里的记录”,但直接写 WHERE id NOT IN (SELECT id FROM ...) 在子查询返回 NULL 时会整个结果为空——这是最常踩的坑。根本原因是 SQL 中任何与 NULL 的等值比较(包括 NOT IN)都返回 UNKNOWN,被当作假值过滤掉。
正确做法是改用 NOT EXISTS,它不依赖值比较,只判断子查询是否返回行:
SELECT name FROM users u WHERE NOT EXISTS ( SELECT 1 FROM orders o WHERE o.user_id = u.id );
-
NOT EXISTS对NULL安全,子查询里哪怕有NULL字段也不影响外层逻辑 - 必须写关联条件(如
o.user_id = u.id),否则变成“只要子查询无结果就全选”,失去反查意义 - 子查询中
SELECT 1是惯用写法,比SELECT *更轻量,数据库通常会忽略实际列内容
LEFT JOIN + IS NULL:更直观的反查询写法
当需要反查字段较多、或想顺便看匹配失败原因时,LEFT JOIN 比子查询更易读且调试友好:
SELECT u.name, u.email FROM users u LEFT JOIN orders o ON u.id = o.user_id WHERE o.user_id IS NULL;
- 关键在
WHERE o.user_id IS NULL,不是o.id IS NULL——因为LEFT JOIN后未匹配的右表行所有字段都是NULL,但用外键字段判空最稳妥 - 如果
orders.user_id允许为NULL,这个写法可能误判;此时应优先用NOT EXISTS - 性能上,现代优化器对这两种写法通常生成相同执行计划,但
LEFT JOIN在涉及多表或复杂条件时更容易加索引提示
子查询里用 NOT IN 的唯一安全场景
只有当你能 100% 确保子查询结果不含 NULL,才可放心用 NOT IN。常见于明确过滤后的主键查询:
SELECT name FROM users WHERE id NOT IN ( SELECT user_id FROM orders WHERE user_id IS NOT NULL );
- 必须显式加
WHERE user_id IS NOT NULL,不能依赖业务假设 - 如果子查询来自视图或复杂嵌套,很难保证无
NULL,这时宁可换NOT EXISTS - MySQL 8.0+ 和 PostgreSQL 支持
NOT IN (VALUES (1),(2))这类字面量列表,无NULL风险,但实用性有限
性能陷阱:相关子查询别漏掉索引
NOT EXISTS 和 NOT IN 都是相关子查询,数据库需对外表每行执行一次子查询。若没索引,性能会断崖式下跌:
- 检查子查询中的关联字段(如
orders.user_id)是否有索引,没有就加:CREATE INDEX idx_orders_user_id ON orders(user_id); - PostgreSQL 中可用
EXPLAIN ANALYZE看是否走了Hash Anti Join或Nested Loop Anti Join;MySQL 则关注type是否为ref或eq_ref - Oracle 用户注意:
NOT EXISTS在某些版本下可能比LEFT JOIN多一次全表扫描,务必实测
反查询看着简单,但 NULL 处理和索引缺失是最容易被跳过的两个点,一漏就查不到数据或查得极慢。
# mysql
# oracle
# ai
# sql
# NULL
# select
# postgresql
# 数据库
# 都是
# 为空
# 这是
# 看着
# 也不
# 走了
# 很难
# 你能
# 这类
# 较多
相关栏目:
【
网站优化151355 】
【
网络推广146373 】
【
网络技术251813 】
【
AI营销90571 】
相关推荐:
Laravel如何集成第三方登录_Laravel Socialite实现微信QQ微博登录
Laravel如何清理系统缓存命令_Laravel清除路由配置及视图缓存的方法【总结】
如何在香港服务器上快速搭建免备案网站?
如何快速搭建二级域名独立网站?
Laravel如何实现URL美化Slug功能_Laravel使用eloquent-sluggable生成别名【方法】
Laravel模型关联查询教程_Laravel Eloquent一对多关联写法
如何确保西部建站助手FTP传输的安全性?
如何快速搭建安全的FTP站点?
Laravel用户密码怎么加密_Laravel Hash门面使用教程
Java垃圾回收器的方法和原理总结
如何在七牛云存储上搭建网站并设置自定义域名?
宙斯浏览器文件分类查看教程 快速筛选视频文档与图片方法
Laravel如何使用Facades(门面)及其工作原理_Laravel门面模式与底层机制
如何在万网利用已有域名快速建站?
晋江文学城电脑版官网 晋江文学城网页版直接进入
Laravel任务队列怎么用_Laravel Queues异步处理任务提升应用性能
Laravel怎么使用Collection集合方法_Laravel数组操作高级函数pluck与map【手册】
如何制作公司的网站链接,公司想做一个网站,一般需要花多少钱?
laravel怎么实现图片的压缩和裁剪_laravel图片压缩与裁剪方法
Laravel Facade的原理是什么_深入理解Laravel门面及其工作机制
Laravel如何使用withoutEvents方法临时禁用模型事件
免费的流程图制作网站有哪些,2025年教师初级职称申报网上流程?
如何获取上海专业网站定制建站电话?
如何在Windows服务器上快速搭建网站?
网站制作大概多少钱一个,做一个平台网站大概多少钱?
JavaScript如何实现类型判断_typeof和instanceof有什么区别
php 三元运算符实例详细介绍
Laravel怎么做缓存_Laravel Cache系统提升应用速度的策略与技巧
Laravel怎么进行数据库事务处理_Laravel DB Facade事务操作确保数据一致性
如何用花生壳三步快速搭建专属网站?
如何在宝塔面板中创建新站点?
如何在橙子建站上传落地页?操作指南详解
如何在浏览器中启用Flash_2025年继续使用Flash Player的方法【过时】
html5的keygen标签为什么废弃_替代方案说明【解答】
如何用免费手机建站系统零基础打造专业网站?
弹幕视频网站制作教程下载,弹幕视频网站是什么意思?
Claude怎样写结构化提示词_Claude结构化提示词写法【教程】
ChatGPT怎么生成Excel公式_ChatGPT公式生成方法【指南】
网页制作模板网站推荐,网页设计海报之类的素材哪里好?
北京网页设计制作网站有哪些,继续教育自动播放怎么设置?
Laravel如何使用Scope本地作用域_Laravel模型常用查询逻辑封装技巧【手册】
JavaScript如何实现倒计时_时间函数如何精确控制
Laravel如何使用.env文件管理环境变量?(最佳实践)
Linux虚拟化技术教程_KVMQEMU虚拟机安装与调优
Laravel策略(Policy)如何控制权限_Laravel Gates与Policies实现用户授权
制作网站软件推荐手机版,如何制作属于自己的手机网站app应用?
如何做网站制作流程,*游戏网站怎么搭建?
Mybatis 中的insertOrUpdate操作
如何在云主机上快速搭建网站?
如何快速打造个性化非模板自助建站?


