谓词exsits用法及与in的使用区别

news2024/11/15 7:54:38

exists用法

大白话的说,exists的执行,是依次拿外层表的每条记录,去和exsits后的子查询表按你所定义的运算规则(如果有的话)做运算,如果存在结果,也就是有返回数据,无论这部分数据有几条,这部分数据内容是什么,exists后的子查询都会返回true,外层表参与运算的这条记录被保留,反之返回false,外层表参与运算的这条记录被舍弃。也就是强调的子查询有返回,而不关注子查询返回什么。下面是从文档中截取的几句话,可以印证说明。
在这里插入图片描述
文档中第一段话说的是对于一个查询结果非空的子查询,如果前面是exists,则子查询返回true,如果是not exists,则返回false。

第二段话说的是exists子查询里面的select子句,通常写成select *,但也可以写成select '任意值’和select 列名的形式。因为像上面说的,外层只关注内层子查询是否有结果数据,而不关注数据本身。需要注意的是如果是select '任意值’的形式例如select 5,那么每次都会返回true,外层所有记录都会被保留。

第三段话其实说的还是只关注子查询是否有结果,不关心结果是什么,哪怕查询的结果行中都是null都没问题,同样返回true。

关于第三段话“对于上面的例子,如果t2包含任何行,哪怕行的内容为null,都会返回true”这里可能有些难理解,我个人当初和null值混淆,当时写的一个例句“select * from t1 exists (select null)”,按照前面所说的exists执行过程来看,子查询没有运算结果时返回false外层表数据舍弃,所以觉得应该是t1表的数据都应该被舍弃,结果是把t1表的所有数据都返回了。后来找了些书看知道为什么开始的想法是错误的了。要想搞清楚这个问题,首先要理解SQL是一个面向集合的语言,也就是操作和返回的数据都是建立在集合的基础上。上面的执行过程其实就是说,当运算结果是一个非空集合时,则返回true,如果是空集,则返回false。其次要明白null在数据库中的含义,null表示的是不确定,未知,可能有值、可能无值、可能存在、可能不存在、可能是任何值、可能不是任何值。更确切的表示的更像是一种状态,而非空值。空值的前提是必须存在,只是没有值。所以从这也能理解null和空集并不等价。如果把null作为集合中一个元素的话,返回null则是返回了一个包含了null元素的集合,而非空集。

这也是开始困扰我的地方,如果没有这方面的困扰这段话可以跳过。

下面直接写几个Demo举例说明一下。

创建3张测试表,学生表student(id,name),课程表course(id,name),成绩表score(sid,cid,score)

-- 创建学生表
drop table if exists student;
create table student(
	id int,
	name varchar(10)
);
insert into student values(1,'小明'),(2,'小华'),(3,'小强');
select * from student;

-- 创建课程表
drop table if exists course;
create table course(
	id int,
	name varchar(10)
);
insert into course values(1,'语文'),(2,'数学'),(3,'英语');
select * from course;

-- 创建成绩表
drop table if exists score;
create table score(
	sid int,
	cid int,
	score int
);
insert into score values(1,1,65),(2,1,70),(2,3,83),(3,1,92),(3,2,87),(3,3,96);
select * from score;

在这里插入图片描述
Q1:找出小华选修的课程课程名。(简单)

select 
	name
from course 		-- 选课程,所以外层表为课程表
where exists(		-- 用外层课程表中的记录逐一和学生表成绩表关联并按指定规则过滤,存在结果返回true,不存在结果返回false
	select 
		* 			
	from student,score						
		where score.cid=course.id			
		  and score.sid=student.id
		  and student.name='小华'			-- 限定小华
);

返回的结果是语文和英语。

Q2:找出选修了全部课程的学生姓名。(这个是有难度的,觉得下面这个sql看懂了exists也差不多懂了)

-- 选修了全部课程,可以翻译成没有一门课程是这个学生不选的。用双重not exists嵌套实现
-- not exists和exists相反,子查询结果为空集时返回true,否则返回false

select
	name
from student s
where not exists(		  -- 如果所有的课程记录都被舍弃,说明学生选修了全部,此时select结果为空集,not exists返回true,该学生被保留
	select 
		name
	from course c
	where not exists(		-- 对于该门课程,如果该学生存在成绩记录则返回false,则舍弃该门课程,继续往下依次查找其它课程
		select 
			*
		from score sc
		where sc.sid=s.id	-- 限定学生
		  and sc.cid=c.id	-- 限定课程
	)
)

查询结果是小强。

其实上面这个sql难理解的地方在于要知道对于中间那一层course表的记录,也是根据最内层子查询的查询结果一条条依次做筛选的,当对所有的课程筛选完才会对外层返回一个true或false的结果。

exists和in的区别

关系上,二者都属于子查询,但区别是in是不相关子查询,exists是相关子查询。因为执行过程中in是先执行子查询得到一张中间结果表,再在外层表和中间表之间做匹配查询。而exists是每次拿外表的数据到子查询中做校验。

执行上,in是将子查询结果表和外层表做hash连接,exists是将外表做loop循环,每次循环再对内表做查询。

执行效率上,普遍说法是in查询时以子查询结果表为驱动表,外表为被驱动表,所以适合子查询数据集小外表数据集大的情况。而exists查询时以外表为驱动表,子查询表为被驱动表,所以适合外表数据集小子查询数据集大的情况。这只是理论上,实际执行时以谁为驱动表谁为被驱动表还要经过优化器的优化,同时还涉及到走不走索引,具体还是要以实际的执行计划为准。

本来想深入的学习一下mysql具体是怎么选择驱动表的,但目前精力和水平都有限。(失业人员,哈哈,还在到处找工作),以后有时间了把这些东西搞清楚再来补上。

参考

1.https://dev.mysql.com/doc/refman/8.0/en/exists-and-not-exists-subqueries.html
2.《SQL进阶教程》(MICK著/吴炎昌译) 1-8.EXISTS谓词的用法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/356530.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL中使用索引优化

目录 一.使用索引优化 数据准备 避免索引失效应用-全值匹配 避免索引失效应用-最左前缀法则 避免索引失效应用-其他匹配原则 1、 2、 3、 4、 5、 一.使用索引优化 索引是数据库优化最常用也是最重要的手段之一,通过索引通常可以帮助用户解决大多数的MySQL的性能优化…

Pandas库入门仅需10分钟

数据处理的时候经常性需要整理出表格,在这里介绍pandas常见使用,目录如下: 数据结构导入导出文件对数据进行操作 – 增加数据(创建数据) – 删除数据 – 改动数据 – 查找数据 – 常用操作(转置&#xff0…

Linux 配置RAID组

目录 配置RAID(软件RAID) 创建RAID组 RAID中出现坏盘如何操作 RAID 添加热备盘 删除RAID组 RAID所解决的问题 提升硬盘的I/O吞吐率 提高硬盘的读写能力 提高硬盘的安全性 进行备份 减少硬盘成本 RAID级别 存储RAID——RAID级别_静下心来敲木鱼的博…

Spring Boot中使用@Autowire装配接口是怎么回事?

在学习使用Spring Boot框架时候,发现了一个特别的现象UserMapper是一个接口,在另一个类中好像直接使用Autowired装配了一个UserMapper对象???我纳闷了一会儿,接口居然可以直接实例对象吗?根据我…

测试开发之Django实战示例 第十三章 上线

在上一章,为其他程序与我们的Web应用交互创建了RESTful API。本章将学习如何创建生产环境让我们的网站正式上线,主要内容有:配置生产环境创建自定义中间件实现自定义管理命令1创建生产环境现在该将Django项目正式部署到生产环境中了。我们将按…

深度解读依赖注入DI源码

spring-framework-5.3.10 版本依赖注入代码的入口在org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory#populateBean 。如果想搞清楚为什么是这里需要去学习下Bean的生命周期,这里就不介绍了。AutowiredAutowired private OrderServic…

电子科技大学操作系统期末复习笔记(五):文件管理

目录 前言 文件管理:基础 基本概念 文件 文件系统 文件系统的实现模型 文件的组成 文件名 文件分类 文件结构 逻辑结构 物理结构 练习题 文件管理:目录 文件控制块FCB FCB:File Control Block FCB信息 目录 基本概念 目…

CAN通信笔记-位时间、Tq及采样点同步

本文框架1.前言2. 位时间2.1 位时间定义2.2 位时间计算3. Tq3.1 Tq的计算3.1.1 举个例子3.2 位时间与Tq的换算4. 采样点同步4.1 硬同步4.2 重同步4.2.1 延长PBS1的重同步4.2.2 缩短PBS2的重同步1.前言 本篇记录些关于CAN的一些学习笔记,说实话CAN协议发展的已经非常…

【项目设计】—— 负载均衡式在线OJ平台

目录 一、项目的相关背景 二、所用技术栈和开发环境 三、项目的宏观结构 四、compile_server模块设计 1. 编译服务(compiler模块) 2. 运行服务(runner模块) 3. 编译并运行服务(compile_run模块) 4…

MicroBlaze系列教程(6):AXI_IIC的使用(24C04 EEPROM)

文章目录 @[toc]AXI_IIC简介MicroBlaze硬件配置常用函数使用示例波形实测参考资料工程下载本文是Xilinx MicroBlaze系列教程的第6篇文章。 AXI_IIC简介 一般情况下,使用FPGA实现I2C协议主要有两种方式:一种是基于Verilog实现起始位、停止位、ACK产生和判断、数据的发送和接收…

1.HTTP及Template介绍

目录 来源 介绍 模板与渲染 Go语言的模板引擎 模板引擎的使用 定义模板文件 解析模板文件 模板渲染 基本示例 模板语法 {{.}} 注释 pipeline 变量 移除空格 条件判断 range with 预定义函数 比较函数 自定义函数 模板的嵌套template block 修改默认的标…

加油站会员管理小程序实战开发教程13

我们上一篇讲解了会员注册的功能,本篇我们介绍一下会员开卡的功能。 会员注册之后,可以进行开卡的动作。一个会员可以有多张会员卡,在微搭中用来描述这种一对多的关系的,我们用关联关系来表达。 登录微搭的控制台,点击数据模型,点击新建数据模型 输入数据源的名称会员卡…

基于 Debain11 构建 asp.net core 6.x 的基础运行时镜像

基于 Debain11 构建 asp.net core 6.x 的基础运行时镜像Linux 环境说明Debian 简介Debian 发行版本关于 Debian 11Linux 常用基础工具Dockerfile 中 RUN 指令RUN 语法格式RUN 语义说明编写 Dockerfile 构建 Runtime 基础镜像ASP.NET Core Runtime 基础镜像Dockerfile 编写Windo…

sklearn主成分分析PCA

文章目录基本原理PCA类图像降维与恢复基本原理 PCA,即主成分分析(Principal components analysis),顾名思义就是把矩阵分解成简单的组分进行研究,而拆解矩阵的主要工具是线性变换,具体形式则是奇异值分解。 设有mmm个nnn维样本X…

【面试题】数组reduce的用法

1. 对数组求和 传统的数组求和方式需要使用forEach循环遍历数组中的每一个元素,然后累加。然而这种方式需要新增一个用于存储累加结果的变量。 function sum(arr) {let res 0arr.forEach(element > res res element);return res }还可以通过数组的reduce方法…

算法笔记(九)—— 暴力递归

暴力递归(尝试) 1. 将问题转化为规模缩小了的同类问题子问题 2. 有明确的不需要的继续递归的条件 3. 有当得到子问题结果之后的决策过程 4. 不记录每一个子问题的解 Question:经典汉诺塔问题 1. 理解清楚,基础三个圆盘的移动…

2.5|iot|嵌入式Linux系统开发与应用|第4章:Linux外壳shell脚本程序编程

1.shell基础 Shell是Linux操作系统内核的外壳,它为用户提供使用操作系统的命令接口。 用户在提示符下输入的每个命令都由shell先解释然后发给Linux内核,所以Linux中的命令通称为shell命令。 通常我们使用shell来使用Linux操作系统。Linux系统的shell是…

高斯课堂 计算机网络(上)

第一章、概述 0、第一章导图 1、计算机网络概述 (1)计算机网络发展历史1:ARPANET->互联网 小写internet是一个宽泛的概念,指的就是互联网 大写Internet是一个专有名词,指的就是我们现在所使用的这样一个全球最大的…

Python(1)变量的命名规则

目录 1.变量的命名原则 3.内置函数尽量不要做变量 4.删除变量和垃圾回收机制 5.结语 参考资料 1.变量的命名原则 ①由英文字母、_(下划线)、或中文开头 ②变量名称只能由英文字母、数字、下画线或中文字所组成。 ③英文字母大小写不相同 实例: 爱_aiA1 print(…