摘要:IN / NOT IN 是 SQL 开发中高频使用的多条件筛选语法,可高效替代多段 OR 语句。但多数开发者仅掌握基础用法,忽略 NOT IN 针对 NULL 值的逻辑缺陷、大数据量索引失效、慢查询隐患等生产级问题。本文从基础语法、实战案例、底层逻辑、高危坑点、性能优化、生产替代方案全方位讲解,适配 MySQL 主流数据库,所有代码可直接落地运行,适合开发自查与面试复盘。
关键词:SQL;MySQL;IN;NOT IN;SQL优化;数据库索引;SQL避坑;慢查询优化
一、前言
在日常业务开发、数据统计、报表查询中,多值条件筛选是刚需场景。如果长期使用 OR 拼接多条件,不仅代码冗余、可读性差,还极易出现语法错误。
此时 IN 和 NOT IN 就是最优解。
但在生产环境中,很多 数据统计异常、查询结果为空、慢查询拖库 问题,根源均来自 NOT IN 的隐性逻辑漏洞和不当使用。
本文结合实战场景,完整梳理 IN / NOT IN 全套知识点,重点解决生产踩坑与性能优化问题。
二、IN / NOT IN 核心定义与基础语法
2.1 核心语义
- IN:匹配字段值存在于指定列表中的数据,属于包含查询
- NOT IN:匹配字段值不存在于指定列表中的数据,属于排除查询
2.2 通用标准语法
适配 MySQL、Oracle、SQL Server 全系列数据库:
IN 语法
|
sql |
NOT IN 语法
|
sql |
三、基础实战案例(可直接运行)
基于业务常用 user 用户表演示基础筛选场景,对比传统 OR 写法与 IN 写法的优劣。
3.1 IN 实战:批量多值匹配
需求:查询年龄为 18、20、25 的所有用户
|
sql |
等价 OR 冗余写法(不推荐):
|
sql |
值越多,IN 语法的简洁性和可维护性优势越明显。
3.2 NOT IN 实战:批量排除匹配
需求:查询年龄非 18、20、25 的所有用户
|
sql |
四、进阶用法:子查询动态筛选(生产高频)
真实开发中极少使用固定值列表,更多通过 子查询动态关联数据,实现跨表筛选。
涉及两张业务表:
- student:学生信息表
- score:学生成绩表,关联字段 student_id
4.1 IN 子查询:查询有成绩的学生
|
sql |
4.2 NOT IN 子查询:查询无成绩的学生(高危场景)
|
sql |
重点:该写法是新手及初级开发高频翻车点,下文详细解析坑点与解决方案
五、生产致命坑:NOT IN + NULL 空值陷阱
5.1 故障现象
当 NOT IN 后的子查询结果中 存在 NULL 值,整条 SQL 查询结果会 直接返回空数据,无报错、无异常,极难排查。
5.2 底层原理
SQL 三值逻辑:True / False / Unknown。
任何值与 NULL 进行比对,结果均为 Unknown,NOT IN 无法匹配未知状态,所有数据都会被判定为不匹配,最终结果集为空。
5.3 标准修复方案
子查询中强制过滤 NULL 值,从根源规避问题:
|
sql |
生产规范:所有 NOT IN 子查询,必须增加 IS NOT NULL 过滤条件
六、IN / NOT IN 性能深度优化
6.1 适用场景划分
- 小数据量、固定少量值:优先使用 IN / NOT IN,语法简洁、可读性高
- 大数据量、子查询结果集庞大:IN 容易触发索引失效、全表扫描,引发慢查询
6.2 生产最优替代方案
针对大数据量、高并发业务,禁止使用 NOT IN,统一使用 NOT EXISTS:
|
sql |
6.3 核心性能对比
- NOT IN:存在 NULL 逻辑坑、大数据量索引失效、全表比对效率低
- NOT EXISTS:基于索引匹配、无空值逻辑缺陷、遍历效率更高,生产首选
七、核心知识点总结
|
plain text |
八、写在最后
IN 和 NOT IN 看似是 SQL 基础语法,实则包含大量生产细节与底层逻辑。很多线上数据异常、慢查询问题,均是开发者忽视空值逻辑、性能特性导致。
掌握 基础用法 + 空值避坑 + 性能优化 + 生产替代方案,才能真正适配企业级开发规范,写出健壮、高效、零BUG 的 SQL 语句。
欢迎点赞、收藏、关注,持续更新 Java / SQL / 数据库优化、后端实战干货!
#SQL #MySQL #数据库 #SQL优化 #后端开发 #编程干货 #数据库避坑 #慢查询优化
&spm=1001.2101.3001.5002&articleId=163151499&d=1&t=3&u=785dda09be3744a0afe058b5355cfcd8)
566

被折叠的 条评论
为什么被折叠?



