mysql中关键词exists的用法实例详解
作者:有梦想的攻城狮 发布时间:2024-01-20 18:41:25
前言
在日常开发中,用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从左到由来看:左面小表,右边大表): exists 比 in 的效率高
外层大表,内层小表(或者将sql从左到由来看:左面大表,右边小表): in 比 exists 的效率高
参考资料
https://www.bilibili.com/video/BV1V64y1q7yi?spm_id_from=333.337.search-card.all.click
来源:https://blog.csdn.net/zhangzehai2234/article/details/124652056


猜你喜欢
- 记录一下如何用python爬取app数据,本文以爬取抖音视频app为例。编程工具:pycharmapp抓包工具:mitmproxyapp自动
- 本文实例讲述了php实现比较全的数据库操作类。分享给大家供大家参考。具体如下:<?php class database {  
- 1.确保系统中有依赖的libaio 软件,如果没有: yum -y
- 在scipy.linalg的函数中,往往会提供两种参数,其一是check_finite,当为True时将进行有限检查,另一类是overwri
- pydev debugger: process 10341 is connecting无法debu今天在Pycharm中debug时无法正常
- Javascript 正常取来源网页的URL只要用: document.referrer就可以了!但,如果来源页是Jav
- 这学期在学python,感觉想写一个东西来巩固自己的基础,因为大二的时候我看过python,所以还是一共花了几个小时写了一个基于mysql的
- 1.在Scrapy工程下新建“middlewares.py”# Importing base64 library because we
- 计算机为数组分配一段连续的内存,从而支持对数组随机访问;由于项的地址在编号上是连续的,数组某一项的地址可以通过将两个值相加得出,即将数组的基
- 如下的实际例子代码可以将查询的结果放入到一张自定义表中,同时可以再从这个自定义的表中查询数据:with AA as(SELECT TICKE
- 一、identity的基本用法1.含义identity表示该字段的值会自动更新,不需要我们维护,通常情况下我们不可以直接给identity修
- 在日常的工作中,保护数据免受未授权用户的侵犯是系统管理员特别关心的问题。如果你目前用的是MySQL,就可以使用一些方便的功能来保护系统,来大
- 可以任意转载,但转载时必须标明原作者charlee、原始链接http://tech.idv2.com/2008/11/03/python-m
- 使用 IE8 时发现其原生的 JSON 解析器存在 Bug,让我们先用 IE8 打开 DEMO 页面体验下。http://lab.grace
- 看了不少js继承的东西也该总结总结了。先说一下大概的理解,有不对的还望指正,也好更正一下三观。另外说明下,下面的例子并非原创基本就是改了个变
- 一、文件内容的分发 应用场景:分批读取共有358086行内容的txt文件,每取1000条输出到一个文件当中# coding=utf-8# 分
- 阅读目录什么是PrmoisePromise的使用最近在看《你不知道的javascript中卷》,发觉作者花了基本一半的篇幅去讲异步和prom
- 前段时间写了个比较简单的批量水印添加的python实现方式,将某个文件夹下面的图片全部添加上水印。今天正好有时间就做了一个UI应用的封装,这
- 一、查看定时策略是否开启show variables like '%event_scheduler%'; * on
- 我的终极整理,供参考# coding:utf-8import matplotlib# 使用 matplotlib中的FigureCanvas