【MySQL系列】MySQL复合查询的学习 _ 多表查询 | 自连接 | 子查询 | 合并查询

news2024/12/24 3:08:17

「前言」文章内容大致是对MySQL复合查询的学习。

「归属专栏」MySQL

「主页链接」个人主页

「笔者」枫叶先生(fy)

MySQL

目录

  • 一、基本查询回顾
  • 二、多表查询
  • 三、自连接
  • 四、子查询
    • 4.1 单行子查询
    • 4.2 多行子查询
    • 4.3 多列子查询
    • 4.4 在from子句中使用子查询
  • 五、合并查询

一、基本查询回顾

前面篇章讲解的mysql表的查询都是对一张表进行查询,在实际开发中这远远不够,下面将讲解复合查询,首先回顾一下基本的查询。

使用的数据库是之前篇章的雇员信息表,员工表(emp)、部门表(dept)和工资等级表(salgrade)
在这里插入图片描述

查询工资高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为大写的J

mysql> select * from emp where (sal > 500 or job = 'MANAGER') and ename like 'J%';

在这里插入图片描述

按照部门号升序而雇员的工资降序排序

mysql> select * from emp order by deptno asc, sal desc;

在这里插入图片描述

使用年薪进行降序排序

mysql> select ename, sal*12+ifnull(comm, 0) as 年薪 from emp order by 年薪 desc;

在这里插入图片描述
注:

  • 由于NULL与任何值做计算得到的结果都是NULL,因此在计算年薪时不能直接用月薪的12倍加上每个员工的奖金,这样可能导致得到的年薪为NULL值。
  • 在计算每个员工的年薪时,应该通过ifnull函数判断员工的奖金是否为NULL,如果不为NULL则ifnull函数返回员工的奖金,如果为NULL则ifnull函数返回0,避免让NULL值参与计算

显示工资最高的员工的名字和工作岗位

解决该问题需要进行两次查询
在这里插入图片描述
此外,这种问题还可以使用子查询,将两句查询语句合并起来,需要将第一次查询的SQL语句用括号括起来。

mysql> select ename, job from emp where sal = (select max(sal) from emp);

在这里插入图片描述

显示工资高于平均工资的员工信息

也是使用子查询解决

mysql> select * from emp where sal > (select avg(sal) from emp);

在这里插入图片描述

显示每个部门的平均工资和最高工资

在group by子句中指明按照部门号进行分组,在select语句中使用avg函数和max函数,分别查询每个部门的平均工资和最高工资

mysql> select deptno, format(avg(sal), 2) 平均, max(sal) 最高 from emp group by deptno;

在这里插入图片描述

显示平均工资低于2000的部门号和它的平均工资

在group by子句中指明按照部门号进行分组,在select语句中使用avg函数查询每个部门的平均工资,在having子句中指明筛选条件为平均工资小于2000

mysql> select deptno, avg(sal) 平均工资 from emp group by deptno having 平均工资 < 2000;

在这里插入图片描述

显示每种岗位的雇员总数,平均工资

mysql> select job, count(*) 人数, format(avg(sal), 2) 平均工资 from emp group by job;

在这里插入图片描述

二、多表查询

上面的基础查询都是在一张表的基础上进行的查询,实际开发中往往数据来自不同的表,所以需要多表查询。

  • 在进行多表查询时,只需要将多张表的表名依次放到from子句之后,用逗号隔开即可,这时MySQL将会对给定的这多张表取笛卡尔积,作为多表查询的初始数据源
  • 多表查询的本质,就是对给定的多张表取笛卡尔积,然后在产生的新表进行查询

笛卡尔积是指给定两个集合A和B,其中A中的每个元素和B中的每个元素都可以组成一个有序对,这些有序对的集合就是A和B的笛卡尔积。

例如,员工表和部门表进行笛卡尔积

员工表:
在这里插入图片描述
部门表:
在这里插入图片描述
两张表进行笛卡尔积

mysql> select * from emp, dept;

在这里插入图片描述
员工表和部门表的笛卡尔积由两部分组成,前半部分是员工表的列信息,后半部分是部门表的列信息
在这里插入图片描述
对员工表和部门表取笛卡尔积时,会先从员工表中选出一条记录与部门表中的所有记录进行组合,然后再从员工表中选出一条记录与部门表中的所有记录进行组合,以此类推,最终得到一张新表
在这里插入图片描述
对多张表取笛卡尔积后得到的数据并不都是有意义的。

比如对员工表和部门表取笛卡尔积时,员工表中的每一个员工信息都会和部门表中的每一个部门信息进行组合,而实际一个员工只有和自己所在的部门信息进行组合才是有意义的,因此需要从笛卡尔积产生的新表筛选出员工的部门号和部门的编号相等记录。
在这里插入图片描述
注意:进行笛卡尔积的多张表中可能会存在相同的列名,这时在选中列名时需要通过表名.列名的方式进行指明,如果有重复的不指明确切一列,就会报错。
在这里插入图片描述

显示雇员名、雇员工资以及所在部门的名字

从题意可以看出,部门名只有dept表中才有,其他数据来源于emp表,即数据来自EMP和DEPT表,因此要联合查询,即多表查询

mysql> select emp.ename, emp.sal, dept.deptno from emp, dept where emp.deptno = dept.deptno;

在这里插入图片描述

显示部门号为10的部门名,员工名和工资

部门名只有部门表中才有,员工名和员工工资只有员工表中才有,因此需要同时使用员工表和部门表进行多表查询,在where子句中指明筛选条件为员工的部门号等于部门编号(筛选符合条件的信息)

mysql> select ename, sal, emp.deptno, dname from emp, dept where emp.deptno = dept.deptno and dept.deptno = 10;

在这里插入图片描述
注意:在筛选部门号等于10的部门时,可以使用员工表中的部门号,也可以使用部门表中的部门编号,因为两列都是一样的。

显示各个员工的姓名,工资,及工资级别

员工名和工资只有员工表中才有,而工资级别只有工资等级表中才有,因此需要同时使用员工表和工资等级表进行多表查询,在where子句中指明筛选条件为员工的工资在losal和hisal之间的记录

mysql> select ename, sal, grade from emp, salgrade where sal between losal and hisal;

在这里插入图片描述

三、自连接

自连接是指在同一张表进行连接查询,也就是说我们不仅可以对不同表进行取笛卡尔积,也可以对同一张表取笛卡尔积

显示员工FORD的上级领导的编号和姓名

可以使用子查询,先对员工表进行查询得到FORD的领导的编号,然后再根据领导的编号对员工表进行查询得到FORD领导的姓名

mysql> select empno, ename from emp where empno = (select mgr from emp where ename = 'FORD');

在这里插入图片描述
也可以使用多表查询(自查询),因为员工表中的mgr字段能够将表中员工的信息和员工领导的信息关联起来。

mysql> select leader.empno, leader.ename from emp leader, emp worder where leader.empno = worder.mgr and worder.ename = 'FORD';

在这里插入图片描述
由于自连接是对同一张表取笛卡尔积,因此在自连接时至少需要给一张表取别名,否则无法区分这两张表中的列。

四、子查询

  • 子查询是指嵌入在其他SQL语句中的查询语句,也叫嵌套查询
  • 子查询可分为单行子查询、多行子查询、多列子查询,以及在from子句中使用的子查询

4.1 单行子查询

单行子查询,是指返回单行单列数据的子查询

显示SMITH同一部门的员工

在子查询中查询SMITH所在的部门号,在where子句中指明筛选条件为员工部门号等于子查询返回的部门号

mysql> select * from emp where deptno = (select deptno from emp where ename = 'SMITH');

在这里插入图片描述
此外,解决该问题也可以使用自连接

4.2 多行子查询

多行子查询,是指返回多行单列数据的子查询

使用in关键字;查询和10号部门的工作岗位相同的雇员的名字,岗位,工资,部门号,但是不包含10自己的

先查询10号部门有哪些工作岗位,在查询时要对结果进行去重,因为10号部门的某些员工的工作岗位可能是相同的
在这里插入图片描述
然后将上述查询作为子查询,在查询员工表时在where子句中使用in关键字,in关键字用于判断员工的工作岗位是子查询得到的若干岗位中的一个


mysql> select ename, job, deptno from emp 
    -> where job in (select distinct job from emp where deptno=10) and deptno<>10;

在这里插入图片描述

实用all关键字;显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号

先查询30号部门员工的工资,进行去重
在这里插入图片描述

将上述查询作为子查询,在查询员工表时在where子句中使用all关键字,all关键字用于判断员工的工资是否高于子查询得到的所有工资

mysql> select ename, sal, deptno from emp where sal > all(select distinct sal from emp where deptno=20);

在这里插入图片描述

使用any关键字;显示工资比部门30的任意员工的工资高的员工的姓名、工资和部门号(包含自己部门的员工)

先查询30号部门员工的工资,然后在查询员工表时在where子句中使用any关键字,判断员工的工资是否高于子查询的得到的工资中的某一个

mysql> select ename, sal, deptno from emp where sal > any(select distinct sal from emp where deptno=30);

在这里插入图片描述

4.3 多列子查询

单行子查询是指子查询只返回单列,单行数据;多行子查询是指返回单列多行数据,都是针对单列而言的,而多列子查询则是指查询返回多个列数据的子查询语句

查询和SMITH的部门和岗位完全相同的所有雇员,不含SMITH本人

先查询SMITH所在部门的部门号和他的岗位,然后将上述查询作为子查询

mysql> select * from emp where (deptno,job) = (select deptno, job from emp where ename = 'SMITH') and ename <> 'SMITH';

在这里插入图片描述
注:

  • 多列子查询得到的结果是多列数据,在比较多列数据时需要将待比较的多个列用圆括号括起来
  • 多列子查询返回的如果是多行数据,在筛选数据时也可以使用in、all和any关键字

4.4 在from子句中使用子查询

  • 子查询语句不仅可以出现在where子句中,也可以出现在from子句中
  • 子查询语句出现from子句中,其查询结果将会被当作一个临时表使用

显示每个高于自己部门平均工资的员工的姓名、部门、工资、平均工资

先查询每个部门的平均工资,这张表当做临时表使用
在这里插入图片描述
然后对员工表和上述的查询结果进行多表查询,在where子句中指明筛选条件为员工的部门号等于临时表中的部门号,并且员工的工资大于临时表中的平均工资

mysql> select ename, emp.deptno, sal, 平均工资 from emp, (select deptno, avg(sal) 平均工资 from emp group by deptno) tmp 
    -> where emp.deptno=tmp.deptno and sal > 平均工资;

在这里插入图片描述
注意:在from子句中使用子查询时,必须给子查询得到的临时表取一个别名,否则查询将会出错

查找每个部门工资最高的人的姓名、工资、部门、最高工资

先查询每个部门的最高工资
在这里插入图片描述
然后对员工表和上述的查询结果进行取笛卡尔积,在where子句中指明筛选条件为员工的部门号等于临时表中的部门号,并且员工的工资等于临时表中的最高工资

mysql> select ename, sal, emp.deptno, 最高工资 from emp, (select max(sal) 最高工资, deptno from emp group by deptno) tmp 
    ->  where emp.deptno=tmp.deptno and sal=最高工资;

在这里插入图片描述

显示每个部门的信息(部门名,编号,地址)和人员数量

按照部门号进行分组,分别查询每个部门的人员数量
在这里插入图片描述
述查询作为子查询放在from子句中,然后对员工表和临时表取笛卡尔积,在where子句中指明筛选条件为员工的部门号等于临时表中的部门号即可

mysql> select dname, dept.deptno, loc, 部门人数 from dept, (select deptno, count(*) 部门人数 from emp group by deptno) 
    -> tmp where dept.deptno = tmp.deptno;

在这里插入图片描述
上述也可以只使用多表查询解决

mysql> select dname, dept.deptno, loc, count(*) 人数 from emp, dept 
    -> where emp.deptno = dept.deptno 
    -> group by dept.deptno, dname, loc;

在这里插入图片描述

五、合并查询

合并查询,是指将多个查询结果进行合并,关键字unionunion all

  • union用于取得两个查询结果的并集,union会自动去掉结果集中的重复行
  • union all也用于取得两个查询结果的并集,但union all不会去掉结果集中的重复行

将工资大于2500或职位是MANAGER的人找出来

查询工资大于2500的员工,查询职位是MANAGER的员工
在这里插入图片描述
可以使用or操作符将where子句中的两个条件关联起来
在这里插入图片描述
也可以使用union将上述的两条查询SQL连接起来,这时将会得到两次查询结果的并集,并且会对合并后的结果进行去重

mysql> select ename, job, sal from emp where sal > 2500 union
    -> select ename, job, sal from emp where sal > 2500 or job = 'MANAGER';

在这里插入图片描述
可以使用union all,结果是不去重
在这里插入图片描述
注意:待合并的两个查询结果的列的数量必须一致,否则无法合并
--------------------- END ----------------------

「 作者 」 枫叶先生
「 更新 」 2023.8.25
「 声明 」 余之才疏学浅,故所撰文疏漏难免,
          或有谬误或不准确之处,敬请读者批评指正。

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

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

相关文章

RabbitMQ的镜像队列

镜像队列 如果 RabbitMQ 集群中只有一个 Broker 节点&#xff0c;那么该节点的失效将导致整体服务的临时性不可用&#xff0c;并且也可能会导致消息的丢失。可以将所有消息都设置为持久化&#xff0c;并且对应队列的durable 属性也设置为 true &#xff0c;但是这样仍然无法…

ubuntu学习(五)----读取文件以及光标的移动

1、读取文件函数原型介绍 ssize_t read(int fd,void*buf,size_t count) 参数说明&#xff1a; fd: 是文件描述符 buf:为读出数据的缓冲区&#xff1b; count: 为每次读取的字节数&#xff08;是请求读取的字节数&#xff0c;读上来的数据保存在缓冲区buf中&#xff0c;同时文…

jmeter递增压测线程组配置

jmeter递增压测线程组配置 新建线程组线程组参数详解及填写其他指标设置 新建线程组 操作位置如图&#xff1a; 线程组参数详解及填写 其他指标设置 其他指标设置可参考另一篇文章&#xff1a; 链接: jmeter 在linux服务器中执行性能测试、监听服务器资源指标

单例模式的相关知识

饿汉模式 package Thread; class Singleton{private static Singleton instance new Singleton();public static Singleton getInstance(){return instance;}private Singleton(){} }public class demo1 {public static void main(String[] args) {Singleton S1 Singleton.ge…

Sentinel dashboard无法查询到应用的限流配置问题以及解决

一。问题引入 使用sentinle-dashboard控制台 项目整体升级后&#xff0c;发现控制台上无法看到流控规则了 之前的问题是无法注册上来 现在是注册上来了。结果看不到流控规则配置了。 关于注册不上来的问题&#xff0c;可以看另一篇文章 https://blog.csdn.net/a15835774652/…

Mybatis与Spring集成配置

目录 具体操作 1.1.添加依赖 1.2创建spring的配置文件 1.3. 注解式开发 Aop整合pagehelper插件 1. 创建一个AOP切面 2. Around("execution(* *..*xxx.*xxx(..))") 表达式解析 前言&#xff1a; 上篇我们讲解了关于Mybatis的分页&#xff0c;今天我们讲Mybatis与…

如何向BertModel增加字符

这里写自定义目录标题 看起来add_special_tokens和add_tokens加入的新token都不会被切分。

paddleclas ImportError: cannot import name ‘Identity‘ from ‘paddle.nn‘

使用paddlepaddle的 paddleclas 官方demos时 &#xff0c;报错如图 ImportError: cannot import name ‘Identity’ from ‘paddle.nn’ 解决方案很简单&#xff1a; 找到调用 Identity 的位置&#xff1a; 注释掉就解决啦 !!! 搞定&#xff01;&#xff01;&#xff01;…

4.14 tcp_tw_reuse 为什么默认是关闭的?

开启 tcp_tw_reuse 参数可以快速复用处于 TIME_WAIT 状态的 TCP 连接时&#xff0c;相当于缩短了 TIME_WAIT 状态的持续时间。 tcp_tw_reuse 是什么&#xff1f; TIME_WAIT 状态的持续时间是 60 秒&#xff0c;这意味着这 60 秒内&#xff0c;客户端一直会占用着这个端口。端…

使用训练工具

HuggingFace上提供了很多已经训练好的模型库&#xff0c;如果想针对特定数据集优化&#xff0c;那么就需要二次训练模型&#xff0c;并且HuggingFace也提供了训练工具。 一.准备数据集 1.加载编码工具 加载hfl/rbt3编码工具如下所示&#xff1a; def load_encode():# 1.加载编…

用C/C++修改I2C默认的SDA和SCL针脚

首先要说明一点&#xff1a;Pico 有两个 I2C&#xff0c;也就是两套 SDA 和 SCL。这点你可以在针脚图中名字看出&#xff0c;比如下图的 Pin 4 和 Pin 5是 I2C1 的&#xff0c;而默认的 Pin 6 和 Pin 7 是 I2C0 的。 默认情况下是只开启了第一个 I2C&#xff0c;也就是只有 I2C…

数据库——缓存数据

文章目录 缓存数据的处理流程是怎样的&#xff1f;为什么要用 Redis/为什么要用缓存&#xff1f; 缓存数据的处理流程是怎样的&#xff1f; 简单来说就是: 如果用户请求的数据在缓存中就直接返回。缓存中不存在的话就看数据库中是否存在。数据库中存在的话就更新缓存中的数据。…

基于云原生网关的流量防护实践

作者&#xff1a;涂鸦 背景 在分布式系统架构中&#xff0c;每个请求都会经过很多层处理&#xff0c;比如从入口网关再到 Web Server 再到服务之间的调用&#xff0c;再到服务访问缓存或 DB 等存储。在下图流量防护体系中&#xff0c;我们通常遵循流量漏斗原则进行流量防护。…

数字孪生赋能工业制造,为制造业带来新机遇与挑战

数字孪生技术是利用模拟仿真技术将实体对象数字化的技术。它基于虚拟现实、人工智能和云计算等技术&#xff0c;能够创建与真实物体相同的数字模型&#xff0c;并通过实时监测和分析手段&#xff0c;为制造企业提供关于该物体的全面数据&#xff0c;从而优化产品开发和生产过程…

《Dive into Deep Learning》

《Dive into Deep Learning》&#xff1a;https://d2l.ai/ Interactive deep learning book with code, math, and discussionsImplemented with PyTorch, NumPy/MXNet, JAX, and TensorFlowAdopted at 500 universities from 70 countries 《动手学深度学习》中文版&#xff1…

dji uav建图导航系列()ROS中创建dji_sdk节点包(一)项目结构

文章目录 1、整体项目结构1.1、 目录launch1.2、文件CMakeLists.txt1.3、文件package.xml1.4、目录include1.4、目录srv在ROS框架下创建一个无人机的节点dji_sdk,实现必需的订阅(控制指令)、发布(无人机里程计)、服务(无人机起飞降落、控制权得很)功能,就能实现一个类似…

C#-集合小例子

目录 背景&#xff1a; 过程: 1.添加1-100数: 2.求和: 3.平均值: 4.代码:​ 总结: 背景&#xff1a; 往集合里面添加100个数&#xff0c;首先得有ArrayList导入命名空间&#xff0c;这个例子分为3步&#xff0c;1.添加1-100个数2.进行1-100之间的总和3.求总和的平均值&…

03.sqlite3学习——数据类型

目录 sqlite3学习——数据类型 SQL语句的功能 SQL语法 SQL命令 SQL数据类型 数字类型 整型 浮点型 定点型decimal 浮点型 VS decimal 日期类型 字符串类型 CHAR和VARCHAR BLOB和TEXT SQLite 数据类型 SQLite 存储类 SQLite 亲和类型(Affinity)及类型名称 Boo…

【微服务】04-Polly实现失败重试和限流熔断

文章目录 1. Polly实现失败重试1.1 Polly组件包1.2 Polly的能力1.3 Polly使用步骤1.4 适合失败重试的场景1.5 最佳实践 2.Polly实现熔断限流避免雪崩效应2.1 策略类型2.2 组合策略 1. Polly实现失败重试 1.1 Polly组件包 PollyPolly.Extensions.HttpMicrosoft.Extensions.Htt…

MaBatis中的分页插件以及特殊字符处理

目录 一、PageHelper介绍 二、PageHelper使用 1. 导入pom依赖 2. Mybatis.cfg.xml 配置拦截器 配置sql映射文件 测试代码 特殊字符处理 2. 使用CDATA 区段 一、PageHelper介绍 PageHelper 是 Mybatis 的一个插件&#xff0c;这里就不扯了&#xff0c;就是为了更加便捷的进…