MySQL——复合查询

1. 基本查询回顾

这里我们还是使用之前的那三张表;

查询工资高于500或岗位为MANAGER的员工,同时要求员工姓名的首字母为大写的J

查询员工信息,按部门号升序而员工工资降序显示

查询员工信息,按年薪降序显示

这里需要注意的就是奖金(comm)可能为NULL,MySQL中NULL是不参与运算的,所以这就可能导致最终年薪为NULL的情况,这时就需要使用ifnull函数来判断一下。

查询工资最高的员工的姓名和岗位

这个问题我们可以分两步来进行,首先我们找出最高工资,然后在根据查出来的结果去查询对应的员工信息。

但是这种写法我们并不推荐,这里我们可以使用子查询,将两条SQL变成一条SQL;

查询工资高于平均工资的员工信息

查询每个部门的平均工资和最高工资

查询每种岗位的雇员总数和平均工资

2. 多表查询

之前我们所有的查询都是在一张表中进行的单表查询,实际开发环境下,我们更多地需要进行多表查询,多表查询的本质,就是对给定的多张表取笛卡尔积,然后在笛卡尔积中进行查询。

我们可以认为MySQL中一切皆表,我们做笛卡尔积后得到的是一张"新表",本质上我们还是在进行单表查询。

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

这里我们首先要分析需求,看看需要显示的都在哪些表中,在这里部门名这个信息在部门表中,而其他信息在员工表中,所以我们需要将两张表联系起来,然后再进行条件筛选,因为做完笛卡尔积后会产生一些无效数据,我们要将无效数据剔除。

显示各个员工的姓名、工资和工资级别

这里还是与上一题的思路一样,我们需要找出题目需求来自于哪些表,这里的工资等级来自于工资表,其他信息来自于员工表,那么我们就需要将员工表和工资表进行笛卡尔积,然后进行条件筛选。

3. 自连接

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

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

解决该问题可以使用子查询,先对员工表进行查询得到FORD的领导的编号,然后再根据领导的编号对员工表进行查询得到FORD领导的姓名。如下:

此外,解决该问题也可以使用自连接,因为员工表中的mgr字段能够将表中员工的信息和员工领导的信息关联起来。如下:

说明一下: 由于自连接是对同一张表取笛卡尔积,因此在自连接时至少需要给一张表取别名,否则无法区分这两张表中的列。

4. 子查询

子查询是指嵌入在其他SQL语句中的查询语句,也叫嵌套查询。

4.1 单行子查询

返回单行单列数据的子查询。

显示SMITH同一部门的员工信息

4.2 多行子查询

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

in关键字:显示和10号部门的工作岗位相同的员工的名字、岗位、工资和部门号,但是不包含10号部门的员工

先查询10号部门有哪些工作岗位,在查询时最好对结果进行去重,因为10号部门的某些员工的工作岗位可能是相同的。如下:

然后我们需要利用上面子查询得到的结果来进一步查询,这里就需要用到in关键字,判断员工的工作岗位是子查询得到的若干岗位中的一个,如果是则符合筛选条件,由于要求筛选出来的员工不包含10号部门的,因此还需要在where子句中指明筛选条件为部门号不等于10。如下:

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

先查询30号部门员工的工资,在查询时最好对结果进行去重,因为30号部门的某些员工的工资可能是相同的。如下:

然后将上述查询作为子查询,在查询员工表时在where子句中使用all关键字,判断员工的工资是否高于子查询得到的所有工资,如果是则符合筛选条件。如下:

本题其实可以等价于求工资高于30号部门的最高工资的员工,可以使用单行子查询来解决;

any关键字:显示工资比30号部门的任意员工的工资高的员工的姓名、工资和部门号,包含30号部门的员工

先查询30号部门员工的工资,然后在查询员工表时在where子句中使用any关键字,判断员工的工资是否高于子查询的得到的工资中的某一个,如果是则符合筛选条件。如下:

但实际这道题也等价于找到工资高于30号部门的最低工资的员工,因此也可以使用单行子查询得到30号部门的最低工资,然后判断员工的工资是否高于子查询得到的最低工资即可,由于要求筛选出来的员工包含30号部门的,因此不需要再对部门号进行过滤。如下:

4.3 多列子查询

返回多列数据的子查询。

显示和SMITH的部门和岗位完全相同的员工信息,不包含SMITH本人

先查询SMITH所在部门的部门号和他的岗位。如下:

然后将上述查询作为子查询,在查询员工表时在where子句中,指明筛选条件为部门号和岗位等于子查询得到的部门号和岗位,并且员工的姓名不为SMITH即可。如下:

说明一下:

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

4.4 在from子句中使用子查询

子查询语句出现from子句中,其查询结果将会被当作一个临时表使用。

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

首先查询每个部门的平均工资。如下:

由于显示信息中包含部门的平均工资,需要同时使用员工表和上述的查询结果进行多表查询,这时可以将上述查询作为子查询放在from子句中,然后对员工表和临时表取笛卡尔积,在where子句中指明筛选条件为员工的部门号等于临时表中的部门号,并且员工的工资大于临时表中的平均工资。如下:

说明一下: 在from子句中使用子查询时,必须给子查询得到的临时表取一个别名,否则查询将会出错。

显示每个部门工资最高的员工的姓名、工资、部门和部门的最高工资

先查询每个部门的最高工资。如下:

将上述查询作为子查询放在from子句中,然后对员工表和临时表取笛卡尔积,在where子句中指明筛选条件为员工的部门号等于临时表中的部门号,并且员工的工资等于临时表中的最高工资。如下:

显示每个部门的部门名、部门编号、所在地址和人员数量

在group by子句中指明按照部门号进行分组,分别查询每个部门的人员数量。如下:

将上述查询作为子查询放在from子句中,然后对员工表和临时表取笛卡尔积,在where子句中指明筛选条件为员工的部门号等于临时表中的部门号即可。如下:

相关推荐
IT 小阿姨(数据库)5 小时前
PostgreSQL etcd 集群介绍
运维·数据库·sql·postgresql·centos·etcd
NPE~5 小时前
[手写系列]Go手写db — — 第五版(实现数据库操作模块)
开发语言·数据库·后端·golang·教程·手写系列·手写数据库
有想法的py工程师6 小时前
PostgreSQL 测试磁盘性能
数据库·postgresql
Zhsh-76 小时前
centos配置ES和MYSQL自动备份
mysql·elasticsearch·centos
尘下吹霜6 小时前
【鉴权架构】SpringBoot + Sa-Token + MyBatis + MySQL + Redis 实现用户鉴权、角色管理、权限管理
spring boot·mysql·mybatis
weixin_441455267 小时前
Mysql MVCC
数据库·mysql
Su-RE7 小时前
【ElasticSearch】text 和 keyword 类型区分
java·数据库·elasticsearch
武子康7 小时前
Java-146 深入浅出 MongoDB 数据插入、批量写入、BSON 格式与逻辑查询and or not操作指南
java·开发语言·数据库·sql·mongodb·性能优化·nosql
奥尔特星云大使7 小时前
MySQL快速构建主从(基于GTID)
数据库·mysql·主从复制