第09章_MySQL子查询

news2024/9/26 5:15:26

第09章_子查询

讲师:尚硅谷-宋红康(江湖人称:康师傅)

官网:http://www.atguigu.com


子查询指一个查询语句嵌套在另一个查询语句内部的查询,这个特性从MySQL 4.1开始引入。

SQL 中子查询的使用大大增强了 SELECT 查询的能力,因为很多时候查询需要从结果集中获取数据,或者需要从同一个表中先计算得出一个数据结果,然后与这个数据结果(可能是某个标量,也可能是某个集合)进行比较。

1. 需求分析与问题解决

1.1 实际问题

image-20230220142204749

现有解决方式:

#方式1:
SELECT salary
FROM employees
WHERE last_name = 'Abel';

SELECT last_name, salary
FROM employees
WHERE salary > 11000;

#方式2:自连接
SELECT e2.last_name, e2.salary
FROM employees e1, employees e2
WHERE e1.last_name = 'Abel' AND e1.salary < e2.salary;
#方式3:子查询
SELECT last_name, salary
FROM employees
WHERE salary > (
                SELECT salary
                FROM employees
                WHERE last_name = 'Abel'
                );

1.2 子查询的基本使用

  • 子查询的基本语法结构:

image-20230220144101534

  • 子查询要包含在括号内
  • 子查询的结果被主查询使用

1.3 子查询的分类

分类方式1:

我们按子查询的结果返回一条还是多条记录,将子查询分为单行子查询多行子查询

  • 单行子查询

image-20230222185333716

  • 多行子查询

image-20230222185350960

  • 单行操作符对应单行子查询,多行操作符对应多行子查询

分类方式2:

我们按子查询是否被执行多次,将子查询划分为相关子查询不相关子查询

  • 相关子查询

    • 如果子查询需要执行多次,即采用循环的方式,先从主查询开始,每次都将主查询的一条记录传入子查询中进行查询,然后再将结果反馈给主查询,这种嵌套的执行方式就称为相关子查询

    • 子查询需要执行多次,而且与主查询穿插进行

  • 不相关子查询

    • 子查询从数据表中查询了数据结果,如果这个数据结果只执行一次,然后这个数据结果作为主查询的条件进行执行,那么这样的子查询叫做不相关子查询
    • 子查询在主查询之前一次执行完成

2. 单行子查询

2.1 单行比较操作符

操作符含义
=equal to
>greater than
>=greater than or equal to
<less than
<=less than or equal to
<>not equal to

2.2 代码示例

题目:查询工资大于149号员工工资的员工的信息

SELECT employee_id, last_name, salary
FROM employees
WHERE salary > (
                SELECT salary
                FROM employees
                WHERE employee_id=149
                );

image-20230220154454064

题目:返回job_id与141号员工相同,salary比143号员工多的员工的姓名,job_id和工资

SELECT last_name, job_id, salary
FROM employees
WHERE job_id = (	
                SELECT job_id
                FROM employees
                WHERE employee_id = 141
                )
AND salary > (
             SELECT salary
             FROM employees
             WHERE employee_id = 143		
             )

题目:返回公司工资最少的员工的last_name,job_id和salary

SELECT last_name, job_id, salary
FROM employees
WHERE salary = (
                SELECT MIN(salary)
                FROM employees
                );

image-20230220155042098

题目:查询与141号员工的manager_id和department_id相同的其他员工的employee_id,manager_id,department_id

实现方式1:不成对比较

SELECT employee_id, manager_id, department_id
FROM employees
WHERE manager_id = (
                    SELECT manager_id
                    FROM employees
                    WHERE employee_id = 141
                    )
AND department_id = (
                    SELECT department_id
                    FROM employees
                    WHERE employee_id = 141
                    )
AND employee_id <> 141;

实现方式2:成对比较

SELECT employee_id, manager_id, department_id
FROM employees
WHERE (manager_id,department_id) = (
                                    SELECT manager_id, department_id
                                    FROM employees
                                    WHERE employee_id = 141
									)
AND employee_id <> 141;

image-20230220155944723

2.3 HAVING中的子查询

题目:查询最低工资大于110号部门最低工资的部门的id和其最低工资

SELECT department_id, MIN(salary)
FROM employees
WHERE department_id IS NOT NULL
GROUP BY department_id
HAVING MIN(salary)> (
                    SELECT MIN(salary)
                    FROM employees
                    WHERE department_id = 110
                    );

image-20230220172247547

2.4 CASE中的子查询

题目:显式员工的employee_id,last_name和location。其中,若员工的department_id与location_id为1800的部门的department_id相同,则location为’Canada’,其余则为’USA’。

SELECT employee_id, last_name, CASE department_id 
WHEN (SELECT department_id FROM departments WHERE location_id = 1800) THEN 'Canada' 
ELSE 'USA' END "location"					
FROM employees;

image-20230220173459731

2.5 子查询中的空值问题

子查询不返回任何行

SELECT last_name, job_id
FROM employees
WHERE job_id = (
                SELECT job_id 
                FROM employees
                WHERE last_name = 'Haas'
                );

2.6 非法使用子查询

多行子查询使用单行比较符

SELECT employee_id, last_name
FROM employees
WHERE salary = (
                SELECT MIN(salary)
                FROM employees
                GROUP BY department_id
                );

3. 多行子查询

3.1 多行比较操作符

操作符含义
IN等于列表中的任意一个
ANY需要和单行比较操作符一起使用,和子查询返回的某一个值比较
ALL需要和单行比较操作符一起使用,和子查询返回的所有值比较
SOME实际上是ANY的别名,作用相同,一般常使用ANY

3.2 代码示例

题目:返回其它job_id的员工中比job_id为‘IT_PROG’的任一员工的工资低的员工的员工号、姓名、job_id 以及salary

SELECT employee_id, last_name, job_id, salary
FROM employees
WHERE job_id <> 'IT_PROG'
AND salary < ANY (
                SELECT salary
                FROM employees
                WHERE job_id = 'IT_PROG'
                );

image-20230222142624915

题目:返回其它job_id的员工中比job_id为‘IT_PROG’的所有员工的工资低的员工的员工号、姓名、job_id 以及salary

SELECT employee_id, last_name, job_id, salary
FROM employees
WHERE job_id <> 'IT_PROG'
AND salary < ALL (
                SELECT salary
                FROM employees
                WHERE job_id = 'IT_PROG'
                );

image-20230222142857330

题目:查询平均工资最低的部门id

SELECT department_id
FROM employees
GROUP BY department_id
HAVING AVG(salary) <= ALL(
                        SELECT AVG(salary)
                        FROM employees
                        GROUP BY department_id
                        )

image-20230222143212425

3.3 空值问题

SELECT last_name
FROM employees
WHERE employee_id NOT IN(
                        SELECT manager_id #筛选出来的记录有null
                        FROM employees
                        );

image-20230222143631157

4. 相关子查询

4.1 相关子查询执行流程

如果子查询的执行依赖于外部查询,通常情况下都是因为子查询中的表用到了外部的表,并进行了条件关联,因此每执行一次外部查询,子查询都要重新计算一次,这样的子查询就称之为关联子查询

相关子查询按照一行接一行的顺序执行,主查询的每一行都执行一次子查询。

image-20230222234127522

4.2 代码示例

题目:查询员工中工资大于本部门平均工资的员工的last_name,salary和其department_id

方式一:相关子查询

SELECT last_name, salary, department_id
FROM employees e1
WHERE salary > (
                SELECT AVG(salary)
                FROM employees e2
                WHERE department_id = e1.department_id
                );	

方式二:在 FROM 中使用子查询

要给这个子查询取别名,并且聚合函数字段也需要取别名
把它当成一张“临时的虚拟的表”来使用。

SELECT e.last_name, e.salary, e.department_id
FROM employees e,(
                SELECT department_id, AVG(salary) avg_sal
                FROM employees
                GROUP BY department_id) t_dept_avg_sal
WHERE e.department_id = t_dept_avg_sal.department_id
AND e.salary > t_dept_avg_sal.avg_sal;

image-20230222160254456

题目:查询员工的id,salary,按照department_name 排序

在ORDER BY 中使用子查询:

SELECT employee_id, salary
FROM employees e
ORDER BY(
        SELECT department_name
        FROM departments d
        WHERE d.department_id = e.department_id 
        )ASC;

image-20230222161234338

题目:若employees表中employee_id与job_history表中employee_id相同的数目不小于2,输出这些相同id的员工的employee_id,last_name和其job_id

SELECT employee_id, last_name, job_id
FROM employees e
WHERE 2 <= (
	SELECT COUNT(*)
	FROM job_history j
	WHERE j.employee_id = e.employee_id 
	)

image-20230222161722684

4.3 EXISTS 与 NOT EXISTS关键字

  • 关联子查询通常也会和 EXISTS操作符一起来使用,用来检查在子查询中是否存在满足条件的行。

  • 在遍历子查询中的行时

    • 如果在子查询中的行满足条件:直接返回 TRUE,不再继续遍历
    • 如果在子查询中的行不存在满足条件:继续遍历,如果全都遍历完都不存在满足条件的行,返回false
  • NOT EXISTS关键字表示如果在子查询中不存在满足条件的行,则返回TRUE,否则返回FALSE

题目:查询公司管理者的employee_id,last_name,job_id,department_id信息

SELECT employee_id, last_name, job_id, department_id
FROM employees e1
WHERE EXISTS(
            SELECT *
            FROM employees e2
            WHERE e1.employee_id = e2.manager_id
            );

题目:查询departments表中,不存在于employees表中的部门的department_id和department_name

SELECT department_id, department_name
FROM departments d
WHERE NOT EXISTS(
                SELECT *
                FROM employees e
                WHERE d.department_id = e.department_id
                );

image-20230222165845693

4.4 相关更新

UPDATE table1 alias1
SET    column = (SELECT expression
                 FROM   table2 alias2
                 WHERE  alias1.column = alias2.column);

使用相关子查询依据一个表中的数据更新另一个表的数据。

题目:在employees中增加一个department_name字段,数据为员工对应的部门名称

# 1)
ALTER TABLE employees
ADD(department_name VARCHAR2(14));

# 2)
UPDATE employees e
SET department_name =  (SELECT department_name 
	                       FROM   departments d
	                       WHERE  e.department_id = d.department_id);

4.4 相关删除

 DELETE FROM table1 alias1
 WHERE column operator (SELECT expression
                        FROM   table2 alias2
                        WHERE  alias1.column = alias2.column);

使用相关子查询依据一个表中的数据删除另一个表的数据。

题目:删除表employees中,其与emp_history表皆有的数据

DELETE FROM employees e
WHERE employee_id in  
           (SELECT employee_id
            FROM   emp_history 
            WHERE  employee_id = e.employee_id);

5. 抛一个思考题

问题:谁的工资比Abel的高?

解答

#方式1:自连接
SELECT e2.last_name, e2.salary
FROM employees e1, employees e2
WHERE e1.last_name = 'Abel' AND e1.salary < e2.salary;
#方式2:子查询
SELECT last_name, salary
FROM employees
WHERE salary > (
                SELECT salary
                FROM employees
                WHERE last_name = 'Abel'
                );

问题:以上两种方式有好坏之分吗?

解答:自连接方式好!

题目中可以使用子查询,也可以使用自连接。一般情况建议你使用自连接,因为在许多 DBMS 的处理过程中,对于自连接的处理速度要比子查询快得多。
可以这样理解:子查询实际上是通过未知表进行查询后的条件判断,而自连接是通过已知的自身数据表进行条件判断,因此在大部分 DBMS 中都对自连接处理进行了优化

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

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

相关文章

Spring MVC 源码 - HandlerAdapter 组件(一)之 HandlerAdapter

HandlerAdapter 组件HandlerAdapter 组件&#xff0c;处理器的适配器。因为处理器 handler 的类型是 Object 类型&#xff0c;需要有一个调用者来实现 handler 是怎么被执行。Spring 中的处理器的实现多变&#xff0c;比如用户的处理器可以实现 Controller 接口或者 HttpReques…

从零开始学typescript

https://coding.imooc.com/learn/list/412.html 公司花钱买的&#xff0c;我边学边做笔记 设置 vscode设置 然后下个Prettier - Code formatter 以后保存就能格式化了 下载ts npm install typescript3.6.4 -g ts版本 npm install -g ts-node8.4.1 node执行ts文件 这样&a…

_linux (TCP协议通讯流程)

文章目录TCP协议通讯流程TCP 和 UDP 对比TCP协议通讯流程 下图是基于TCP协议的客户端/服务器程序的一般流程: 服务器初始化: 调用socket, 创建文件描述符;调用bind, 将当前的文件描述符和ip/port绑定在一起;如果这个端口已经被其他进程占用了, 就会bind失 败;调用listen, 声…

FPGA入门系列15--SPI(文末有易灵思核心板及配套下载线)

文章简介 本系列文章主要针对FPGA初学者编写&#xff0c;包括FPGA的模块书写、基础语法、状态机、RAM、UART、SPI、VGA、以及功能验证等。将每一个知识点作为一个章节进行讲解&#xff0c;旨在更快速的提升初学者在FPGA开发方面的能力&#xff0c;每一个章节中都有针对性的代码…

国家推进招投标全过程电子签,契约锁帮助组织减负91%

根据某工程建设集团反馈&#xff0c;电子签章的应用帮助招投标工作实现&#xff1a;“参与方5分钟内线上实名认证&#xff1b;招标、中标通知等格式文件最快2分钟完成盖章&#xff1b;标书等大体量文件20分钟内盖章生成&#xff1b;专家实名认证远程评标、10分钟完成线上开标&a…

leetcode 502. IPO(上市,3种方法)

假设leetcode 即将上市&#xff0c;如何筹集资金的问题。 有两个数组profits和capital, 分别代表第 i 个项目有多少净利润 和 需要多少启动资金。 手上的原始资金是w, 用这个w的资金去启动项目&#xff0c;完成项目之后净利润会加到w上&#xff0c;再做下一个项目&#xff0c; …

硬件原理图中的“英文缩写”大全

设计原理图时&#xff0c;网络标号要尽量简洁眀了。本文总结了一下基本的表示方法&#xff0c;供大家参考。常用控制接口 EN&#xff1a;Enable&#xff0c;使能。使芯片能够工作。要用的时候&#xff0c;就打开EN脚&#xff0c;不用的时候就关闭。有些芯片是高使能&#xff0c…

SPI机制源码:JDK Dubbo Spring

JDK 17 Dubbo 3.1.6 JDK SPI JDK SPI在sql驱动类加载、以及slf4j日志实现加载方面有具体实现。 示例 public class Test {private static final Logger logger LoggerFactory.getLogger(Test.class);public static void main(String[] args) {ServiceLoader<JdkSpiServi…

软件测试计划怎么写?模板在这呢

目录 第1章 引言 第2章 项目背景 第3章质量目标 第4章 资源需求 第5章 测试策略 第6章 测试计划 总结感谢每一个认真阅读我文章的人&#xff01;&#xff01;&#xff01; 重点&#xff1a;配套学习资料和视频教学 第1章 引言 1.1目的 简述本计划的目的&#xff0c;旨…

【THREE.JS学习(3)】使用THREEJS加载GeoJSON地图数据

本文接着系列文章&#xff08;2&#xff09;进行介绍&#xff0c;以VUE2为开发框架&#xff0c;该文涉及代码存放在HelloWorld.vue中。相较于上一篇文章对div命名class等&#xff0c;该文简洁许多。<template> <div></div> </template>接着引入核心库i…

RPC(3)--基于 Nacos 的服务发现与负载均衡版

nacos:提供了一组简单易用的特性集&#xff0c;帮助您快速实现动态服务发现、服务配置、服务元数据及流量管理。Nacos 是构建以“服务”为中心的现代应用架构 (例如微服务范式、云原生范式) 的服务基础设施。 nacos架构如下(图片来源) 依赖包&#xff1a; <dependency>…

国内领先的十大API接口排行

应用程序编程接口API即&#xff08;Application Programming Interface&#xff09;&#xff0c;现在众多企业的应用系统中常用的开放接口&#xff0c;对接相应的系统、软件功能&#xff0c;简化专业化的程序开发。 一、百度API 百度API超市开通1136个数据服务接口。 网址&a…

git 的使用方法 (下 - 远程仓库和图形化)

目录前言&#xff1a;一、什么是协同开发二、Gitee 使用协同开发1. 首先注册一个码云账号2. 新建一个仓库3. 根据下图把新建仓库设置为开源4. 在远端合并分支的方法5. 链接 git 远程6. 提交&#xff08;同步&#xff09;远程7. 远程拉取至本地8. 远程分支三、git 图形化的使用1…

ROS2手写接收IMU数据(Imu)代码并发布

目录前言接收IMU数据IMU的串口连接问题python接收串口数据python解析数据ROS2发布IMU数据可视化IMU数据效果前言 在前面测试完了单独用激光雷达建图之后&#xff0c;一直想把IMU的数据融合进去&#xff0c;由于经费的限制&#xff0c;忍痛在淘宝上买了一款便宜的IMU—GY95T&am…

实验室设计|兽医实验室设计|SICOLAB

新建兽医实验室时&#xff0c;需要考虑以下几个方面&#xff1a;&#xff08;1&#xff09;实验室建筑设计&#xff1a;实验室建筑设计应充分考虑实验室的功能需求&#xff0c;例如安全、通风、排水、电力等方面的设计&#xff0c;确保实验室内部环境的稳定和安全。&#xff08…

XX项目自动化测试方案模板,你学会了吗?

目录 1、引言 2、自动化实施目标 3、自动化技术选型 4、测试环境需求 5、人员进度安排 总结感谢每一个认真阅读我文章的人&#xff01;&#xff01;&#xff01; 重点&#xff1a;配套学习资料和视频教学 1、引言 文档版本 版本 作者 审批 备注 V1.0 Vincent XXX …

selenium环境安装及使用

selenium简介官网https://www.selenium.dev简介用于web浏览器测试的工具支持的浏览器包括IE&#xff0c;Firefox,Chrome&#xff0c;edge等使用简单&#xff0c;可使用java&#xff0c;python等多种语言编写用例脚本主要由三个工具构成&#xff0c;webdriver,IDE,web自动化环境…

【深度学习】优化器

1.什么是优化器 优化器是在深度学习的反向传播过程中&#xff0c;指引损失函数&#xff08;目标函数&#xff09;的各个参数往正确的方向更新合适的大小&#xff0c;使得更新后的各个参数让目标函数不断逼近全局最小点。 2.优化器 2-1 BGD 批量梯度下降法&#xff0c;是梯度下…

【阿旭机器学习实战】【33】中文文本分类之情感分析--朴素贝叶斯、KNN、逻辑回归

【阿旭机器学习实战】系列文章主要介绍机器学习的各种算法模型及其实战案例&#xff0c;欢迎点赞&#xff0c;关注共同学习交流。 目录1.查看原始数据结构2.导入数据并进行数据处理2.1 提取数据与标签2.2 过滤停用词2.3 TfidfVectorizer将文本向量化3.利用不同模型进行训练与评…

如何使用HTTPS加密保护网站?

加密 Web 内容并不是什么新鲜事&#xff1a;自发布通过SSL/TLS协议来加密 Web 内容的规范以来&#xff0c;已经过去了近 20 年。然而&#xff0c;近年来&#xff0c;运行安全的HTTPS加密 Web 服务器已经从一种选择变成了一种安全防护的必需品。攻击者继续寻找并找到窃取用户和W…