mysql中exists的用法详解

这篇具有很好参考价值的文章主要介绍了mysql中exists的用法详解。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

在日常开发中,用mysql进行查询的时候,有一个比较少见的关键词exists,我们今天来学习了解一下这个
exists这个sql关键词的用法,这样在工作中遇到一些特定的业务场景就可以有更加多样化的解决方案

语法解释

语法

SELECT column1 FROM t1 WHERE [conditions] and EXISTS (SELECT * FROM t2 );

说明
  • 括号中的子查询并不会返回具体的查询到的数据,只是会返回true或者false,如果外层sql的字段在子查询中存在则返回true,不存在则返回false
  • 即使子查询的查询结果是null,只要是对应的字段是存在的,子查询中则返回true,下面有具体的例子
执行过程

1、首先进行外层查询,在表t1中查询满足条件的column1
2、接下来进行内层查询,将满足条件的column1带入内层的表t2中进行查询,
3、如果内层的表t2满足查询条件,则返回true,该条数据保留
4、如果内层的表t2不满足查询条件,则返回false,则删除该条数据
5、最终将外层的所有满足条件的数据进行返回


贴个链接,mysql官方对于这个命令的说明: https://dev.mysql.com/doc/refman/8.0/en/exists-and-not-exists-subqueries.html;喜欢看英文原版说明的可以来这里看一下

使用案例

环境准备

👉 mysql版本: 8.0.28

👉 数据库表设计:

  • 学生表: t_student
CREATE TABLE `t_student` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT '' COMMENT '学生姓名',
  `age` int NOT NULL COMMENT '年龄',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=37 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='学生表';

导入部分数据


INSERT INTO `t_student` (`id`, `name`, `age`)
VALUES
   (1, '小张', 10),
   (2, 'chenille', 13),
   (3, '小王', 15),
   (4, '小米', 11),
   (5, 'dong', 13),
   (6, 'xi', 12),
   (7, 'chenille', 13),
   (8, '小王地方', 15),
   (9, '米来', 11),
   (10, 'dong', 13),
   (11, '呵呵', 12),
   (12, 'chenille', 13),
   (13, '小赵', 15),
   (14, '小米-0', 11),
   (15, 'bei', 13),
   (16, 'xi-xx', 12),
   (17, 'chenille', 13),
   (18, '小王-hehe', 15),
   (19, '小米-qian', 11),
   (20, 'dong', 13),
   (21, 'xi', 12),
   (22, 'chenille', 13),
   (23, '小王-1', 15),
   (24, '小米-2', 11),
   (25, 'dong-3', 13),
   (26, 'xi-0', 12),
   (27, 'chenille-4', 13),
   (28, '小王-4', 15),
   (29, '小米-7', 11),
   (30, 'dong-1', 13),
   (31, 'xi-5', 12),
   (32, '貔貅', 10),
   (33, '耄耋', 12),
   (34, '饕餮', 9),
   (35, '龙', 13),
   (36, '青牛', 12);


  • 班级学生表:t_class_student
CREATE TABLE `t_class_student` (
  `id` int unsigned NOT NULL AUTO_INCREMENT,
  `student_id` int NOT NULL COMMENT '学生ID',
  `class_id` int NOT NULL COMMENT '班号',
  `class_name` varchar(100)  DEFAULT '' COMMENT '班级名称',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=32 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='班级学生表';

导入部分数据

 INSERT INTO `t_class_student` (`id`, `student_id`, `class_id`, `class_name`)
VALUES
	(1, 1, 1, '一年级1班'),
	(2, 2, 1, '一年级1班'),
	(3, 3, 1, '一年级1班'),
	(4, 4, 1, '一年级1班'),
	(5, 5, 1, '一年级1班'),
	(6, 6, 1, '一年级1班'),
	(7, 7, 1, '一年级1班'),
	(8, 8, 1, '一年级1班'),
	(9, 9, 1, '一年级1班'),
	(10, 10, 1, '一年级1班'),
	(11, 11, 2, '一年级2班'),
	(12, 12, 2, '一年级2班'),
	(13, 13, 2, '一年级2班'),
	(14, 14, 2, '一年级2班'),
	(15, 15, 2, '一年级2班'),
	(16, 16, 2, '一年级2班'),
	(17, 17, 2, '一年级2班'),
	(18, 18, 2, '一年级2班'),
	(19, 19, 2, '一年级2班'),
	(20, 20, 2, '一年级2班'),
	(21, 21, 3, '二年级2班'),
	(22, 22, 3, '二年级2班'),
	(23, 23, 3, '二年级2班'),
	(24, 24, 3, '二年级2班'),
	(25, 25, 3, '二年级2班'),
	(26, 26, 3, '二年级2班'),
	(27, 27, 3, '二年级2班'),
	(28, 28, 3, '二年级2班'),
	(29, 29, 3, '二年级2班'),
	(30, 30, 3, '二年级2班'),
	(31, 31, 4, '三年级1班');
    (32, 32, 4, null);
 

常用查询

已分配班级的学生名单 👇

select * from t_student as s where exists (select student_id from t_class_student where student_id = s.id);

未分配班级的学生名单 👇

select * from t_student as s where not exists (select student_id from t_class_student where student_id = s.id);

已分配 三年级1班 的学生名单 👇

select * from t_student as s where exists (select student_id from t_class_student where student_id = s.id and class_id = 4);

已分配 并且班级是 一年级1班 和 一年级2班 的学生名单 👇

select * from t_student as s where exists (select student_id from t_class_student where student_id = s.id and class_id in (1, 2) );

查询到的字段为null,但是子查询返回的结果为true 👇

select * from t_student as s where exists (select class_name from t_class_student where student_id = s.id and class_id = 4);

查询全部学生名单 👇

select * from t_student as s where exists (select student_id from t_class_student where 1=1);

已分配 三年级1班 的并且年龄大于10岁的学生名单 👇

select * from t_student as s where age > 10 and exists (select student_id from t_class_student where student_id = s.id and class_id = 4);

exists与in的效率比较

上面的这些查询其实也可以通过 in 关键字来实现,下面我们写一下 in 关键字对应的查询语句,

通过 in 实现已分配班级的学生名单 👇

select * from t_student as s where id in (select student_id from t_class_student where student_id = s.id);

通过 in 实现未分配班级的学生名单 👇

select * from t_student as s where id not in (select student_id from t_class_student where student_id = s.id);

下面我们来分析一下这两个关键字使用效率到底那个更高呢?

循环嵌套查询执行原理

👉 循环由外向内,外层循环执行一次,内层循环则需要完整的执行一次,内层执行执行完后返回执行结果,外层循环继续执行,直到外层循环完全执行完成

循环优化策略

👉 有了上面的执行原理的说明,我们明白了一个道理:内层循环次数的多少不会影响到外层的次数,但是外层循环的次数直接会影响到内层循环的次数,外层循环每多一次,内层循环就需要多完整的一次循环,所以我们优化的目标其实就是使外层的循环次数尽量少,总结来说:小表驱动大表。小表就是外层循环,大表就是内层循环,也就是尽量减少外层循环的次数

exists和in查询原理的区别

👀 exists : 外表先进行循环查询,将查询结果放入exists的子查询中进行条件验证,确定外层查询数据是否保留

👀 in : 先查询内表,将内表的查询结果当做条件提供给外表查询语句进行比较

结论

通过上面的优化策略分析和exists和in的查询原理的分析,将这两块内容结合起来其实就得出了我们想要的一个结论:


  • 外层小表,内层大表(或者将sql从左到由来看:左面小表,右边大表): existsin 的效率高
  • 外层大表,内层小表(或者将sql从左到由来看:左面大表,右边小表): inexists 的效率高

  • 参考资料
    https://www.bilibili.com/video/BV1V64y1q7yi?spm_id_from=333.337.search-card.all.click

总结

上面我们简单介绍了一下平时我们比较少用到的一个exists的关键字,通过一些使用的实例,大家也可以基本上了解了它的使用方法,在以后的日常工作中,我们在碰到一些查询问题的时候,这个时候就有了更加多样化的选择方案啦,希望这篇文章对大家有帮助,谢谢文章来源地址https://www.toymoban.com/news/detail-443120.html

到了这里,关于mysql中exists的用法详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • MySQL Select 查询语句详解及高级用法

    MySQL是一个开源的关系型数据库管理系统,支持多种操作语言,其中最基础、最常用的命令之一就是SELECT语句。在本篇文章中,这里将详细介绍MySQL SELECT语句的各个方面,从最基本的查询语句,到更高级的技巧和功能。 SELECT语句用于从表格中检索数据。其基本语法如下: sq

    2024年02月08日
    浏览(46)
  • mysql的JOIN用法详解-附带查询示例

    在 SQL 中,JOIN 是用于将多个表中的数据连接在一起的操作。它通过指定连接条件将两个或多个表中符合条件的行组合起来,产生一个新的结果集。 SQL 中常见的 JOIN 类型包括 INNER JOIN 、 LEFT JOIN 、 RIGHT JOIN 和 FULL OUTER JOIN 。 下面详细介绍这些 JOIN 类型的用法: 在连接条件中,

    2024年04月23日
    浏览(43)
  • MySQL中的@i:=@i+1用法详解

    在MySQL中, @i:=@i+1 是一个非常有用的表达式,用于在查询中生成一个递增的序列号。它可以帮助我们对结果进行编号,或者在需要连续的数字序列时提供便利。 我们先来了解一下MySQL中的用户变量。用户变量是一个用户定义的变量,其以@开头。我们可以在查询中使用用户变量

    2024年02月16日
    浏览(33)
  • mysql中SUBSTRING_INDEX函数用法详解

    MySQL中的SUBSTRING_INDEX函数用于从字符串中提取子字符串,其用法如下: 参数说明: str :要提取子字符串的原始字符串。 delim :分隔符,用于确定子字符串的位置。 count :指定要返回的子字符串的数量。如果为正数,则从字符串的起始位置开始计数;如果为负数,则从字符串

    2024年04月23日
    浏览(53)
  • Mysql中的find_in_set() 函数用法详解及使用场景

    一、find_in_set() 函数详解 示例: 相信大家看完以上示例就知道这个函数的大概作用了,以下是MySQL手册中官方说明 概括一下就是(前一个字符串是A,后一个字符串是B): 如果B字符串包含A字符串:则返回大于0的值,这个值就是A字符串在B字符串的所在位置; 如果B字符串不

    2024年02月13日
    浏览(43)
  • MySQL in和exists的取舍

    之前说过要小表驱动大表,即先遍历小表再遍历大表,接下来看一下in和exists的区别 in 先执行子查询,适合于外表大而内表小的情况 in的参数是子查询时,会将子查询结果存储在一张临时的表中(内联视图),然后扫描整个视图 exists 以外层表作为驱动表,外层表先被访问,适合

    2024年01月23日
    浏览(46)
  • MySQL EXISTS 语句和IN语句有啥区别

    在 MySQL 中,`EXISTS` 和 `IN` 是用于子查询的两种不同方式,它们有一些区别: 1. **IN 语句**:    - `IN` 子句用于在 WHERE 子句中指定多个值,并检查主查询中的某个列是否在子查询返回的结果集中。    - `IN` 子句适用于子查询返回单列多行结果的情况。    - `IN` 子句通常在子查

    2024年04月11日
    浏览(51)
  • The service already exists! 安装mysql数据库错误!

    当你输入mysql install命令时报The service already exists! 报错的原因是服务已经存在! 说明你之前可能已经装过了。 解决方法: 输入sc delete mysql 提示DeleteService 成功,则表示删除成功,你就可以重新输入mysqld install了。 最后显示Service successfully installed.则代表安装成功,接下来启动

    2024年02月05日
    浏览(60)
  • MySQL初始化之后启动报错(mysqld: Table ‘mysql.plugin‘ doesn‘t exist)

    初始化之后,服务无法启动。错误日志error-log 报错如下: (mysql库下的系统表不存在) 系统表 不存在,数据库刚进行完初始化呀,不合理呀? 排出了目录权限问题 半同步插件的参数在初始化的时候不能开启 处理方式是 注释掉 下面参数,重新初始化。 完结撒花。

    2024年02月04日
    浏览(50)
  • not in效率低(MYSQL的Not IN、not EXISTS如何优化)

    【版权所有,文章允许转载,但须以链接方式注明源地址,否则追究法律责任】 【创作不易,点个赞就是对我最大的支持】 仅作为学习笔记,供大家参考 总结的不错的话,记得点赞收藏关注哦! 原SQL使用的是NOT IN 原因分析:我用了两条sql来解决,第一条sql去查了一组id来排

    2024年02月11日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包