游乐游手机版
首页/数据库/文章详情

MySQL中IN与EXISTS用法对比零基础学习笔记

时间:2026-07-24 19:30
本文适合刚接触子查询的MySQL初学者。通过同一套「学生 成绩」示例数据,清晰讲解 IN 和 EXISTS 的用法与区别。 一、它们是干什么的 在 MySQL 数据库查询中,IN 和 EXISTS 这两个关键字经常与子查询搭配使用,共同完成数据过滤任务。简单来说,就是先(或同时)参考另一张表的数据,

本文适合刚接触子查询的MySQL初学者。通过同一套「学生/成绩」示例数据,清晰讲解 INEXISTS 的用法与区别。

MySQL中的IN和EXISTS零基础笔记总结

一、它们是干什么的

在 MySQL 数据库查询中,INEXISTS 这两个关键字经常与子查询搭配使用,共同完成数据过滤任务。简单来说,就是先(或同时)参考另一张表的数据,再决定当前表的哪些行应该被保留。

可以先记住一句通俗版的理解:

关键字通俗理解
IN左边这个值,是否出现在右边的名单里?
EXISTS对当前这一行,括号里的子查询能否至少返回一行?

二、准备示例数据

学生表 students

student_idname
1小明
2小红
3小刚

成绩表 scores

score_idstudent_idsubjectscore
1011语文90
1021数学85
1032语文92

结论:小明、小红有成绩记录;小刚没有成绩记录

三、IN:在不在名单里

3.1 固定名单

SELECT *FROM studentsWHERE student_id IN (1, 2, 5);

含义:查询学号为 1、2 或 5 的学生。

  • 在名单里 → 条件为真,保留该行
  • 不在名单里 → 条件为假,丢弃该行

3.2 名单来自子查询

需求:找出有成绩记录的学生

SELECT *FROM studentsWHERE student_id IN (  SELECT student_id FROM scores);

执行逻辑:

  1. 先执行括号内的子查询:从 scores 表获取 student_id 列表,例如 (1, 1, 2),等同于名单 (1, 2)
  2. 再扫描 students 表:检查每个学生的学号是否出现在名单中
  3. 在名单中的保留

逐步分析:

学生student_id在名单里?结果
小明1保留
小红2保留
小刚3丢弃

查询结果:

student_idname
1小明
2小红

四、EXISTS:存不存在关联行

同样的需求:找出有成绩记录的学生

SELECT *FROM students sWHERE EXISTS (  SELECT 1  FROM scores sc  WHERE sc.student_id = s.student_id);

4.1 怎么理解

外层查询的每一行学生,执行一次内层查询:

  • 内层查询能返回至少一行 → EXISTS 结果为真 → 保留该学生
  • 内层查询返回零行 → 结果为假 → 丢弃该学生

SELECT 1 只是占位符:EXISTS 只关心子查询是否有结果行,不关心具体查询内容。

4.2 逐行走一遍

小明(id=1)

  • 成绩表里是否存在 student_id = 1 的记录?存在 → 保留

小红(id=2)

  • 是否存在 student_id = 2 的记录?存在 → 保留

小刚(id=3)

  • 是否存在 student_id = 3 的记录?不存在 → 丢弃

结果与上面 IN 写法一致:小明、小红。

五、NOT EXISTS:找出「没有成绩」的学生

SELECT *FROM students sWHERE NOT EXISTS (  SELECT 1  FROM scores sc  WHERE sc.student_id = s.student_id);
学生有没有成绩NOT EXISTS保留?
小明
小红
小刚

结果:

student_idname
3小刚

也可以写成:

SELECT *FROM studentsWHERE student_id NOT IN (  SELECT student_id FROM scores);

在这组干净数据下,结果同样是小刚。

小提示:NOT IN 的子查询结果中如果包含 NULL 值,会导致预期之外的行为;很多场景下更推荐使用 NOT EXISTS。初学者先了解这个差异即可。

六、IN 和 EXISTS 怎么选(入门版)

很多业务场景下,两者能写出等价的结果,只是思考角度不同:

INEXISTS
思考方式先获取一份值列表,判断值是否在其中对当前行提问:关联表中是否有匹配行
直观写法id IN (1,2,3)id IN (子查询)EXISTS (带关联条件的子查询)
适合场景列表较短、语义就是「属于某个集合」语义就是「是否存在关联数据」

关于性能:谁更快取决于数据量、索引和优化器策略,不要死记「永远谁更快」。入门阶段优先:写对、读得懂

七、和外键的一点联系(可选)

  • 外键约束:插入数据时就不允许指向不存在的学生
  • IN / EXISTS:查询时筛选「有没有关联成绩」等

一个是写数据时的规则,一个是查数据时的过滤手段,结合起来理解「表与表之间的关联方式」。

八、核心要点回顾

IN:值是否在这个列表里。

EXISTS:对当前行,子查询是否至少存在一行。

NOT EXISTS:对当前行,是否不存在关联行。

同一道题「有成绩的学生」:

  • IN:学号是否出现在成绩表的学号列表中
  • EXISTS:该学生在成绩表里能否找到记录

结果可以一样,思考问题的角度不同。

九、练习

  1. IN 查出有成绩的学生(默写一遍)。
  2. EXISTS 再写一遍。
  3. NOT EXISTS 查出没有成绩的学生。

能不看笔记写出来,这部分就算过关了。

笔记整理自零基础学习过程,示例表为 students / scores。

来源:https://www.jb51.net/database/368009bza.htm
上一篇MySQL多条查询结果纵向拼接完整实现方法详解 下一篇MySQL DATE_ADD函数日期加减操作详解
本站内容用于信息整理与展示,如有侵权或内容问题请及时联系处理。

相关推荐

补充同频道和同主题内容,方便继续浏览更多相关内容。

同类最新

继续查看同栏目最近更新的文章。

更多
自增主键值从何而来?深入理解原理,告别只会auto_increment
数据库 · 2026-07-25

自增主键值从何而来?深入理解原理,告别只会auto_increment

KingbaseES推荐使用serial、bigserial、显式sequence或identity列实现自增主键。serial创建integer并关联序列,bigserial对应bigint;显式sequence可自定义起始值等参数;identity有generatedbydefault(允许指定值)与always(禁止)两种模式。

Linux下瀚高数据库授权文件过期及替换解决方案
数据库 · 2026-07-25

Linux下瀚高数据库授权文件过期及替换解决方案

在银河麒麟系统下,瀚高数据库hgdb-4 5试用授权20天到期后需替换正式授权文件。正确操作:停止服务,备份旧文件,将授权文件复制到 opt highgo hgdb-4 5 etc lic 并命名为hgdb lic,设置权限600和属主highgo:highgo,再启动服务。禁止直接修改data目录下的license info文件。

Oracle BLOB实时同步的5大技术挑战与难点解析
数据库 · 2026-07-25

Oracle BLOB实时同步的5大技术挑战与难点解析

OracleBLOB实时同步面临分片组装、多列隔离、长事务跨窗口、事务回滚及大对象资源控制等技术挑战,必须在日志中精确还原完整字段值,才能保证源端与目标端数据完全一致,这对同步系统的稳健性提出了高要求。

MySQL禁用redo日志导致全备失败
数据库 · 2026-07-25

MySQL禁用redo日志导致全备失败

MySQL全量备份失败是由于数据定义语言操作触发排序索引构建,禁用重做日志导致XtraBackup无法获取一致性备份。测试验证表明,优化表语句即使无数据也会触发该问题。根本原因在于排序索引构建过程跳过了重做日志记录,破坏了备份的一致性。

Kafka架构图优化与改进的全面详细步骤与实践指南
数据库 · 2026-07-25

Kafka架构图优化与改进的全面详细步骤与实践指南

Kafka作为实时数据流处理的核心中间件,其底层架构虽已相当成熟,但在实际生产环境中,要充分发挥其性能潜力,仍需落实到具体的调优与架构改造上。核心目标可归纳为三点:如何承载更高的吞吐量、如何保障数据不丢失、以及故障发生时如何快速恢复。本文将从这几个关键方向出发,深入探讨如何真正榨干Kafka集群的性