[MySQL]MySQL复合查询
文章目录
0. 准备测试表
准备三张表,分别是员工表(emp)、部门表(dept)和工资等级表(salgrade),后续所要进行的查询操作都将以这三张表作为数据源,包括基本查询和复合查询。
员工表(emp)中包含如下字段:
- 雇员编号(empno)。
- 雇员姓名(ename)。
- 雇员职位(job)。
- 雇员领导编号(mgr)。
- 雇佣时间(hiredate)。
- 工资月薪(sal)。
- 奖金(comm)。
- 部门编号(deptno)。
员工表的表结构及表内数据:


部门表(dept)中包含如下字段:
- 部门编号(deptno)。
- 部门名称(dname)。
- 部门所在地点(loc)。
部门表的结构和表内数据:

工资等级表(salgrade)中包含如下字段:
- 等级(grade)。
- 此等级最低工资(losal)。
- 此等级最高工资(hisal)。
工资等级表的结构和表内数据:

1. 基本查询回顾
示例1: 查询工资高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为大写的J。

示例2: 按照部门号升序而雇员的工资降序排序。

示例3: 使用年薪进行降序排序。

- null加上任何值都是null,因此需要使用ifnull函数来判断奖金数。
- 在这里ifnull函数的判断逻辑是如果奖金为null,返回0,奖金不为null,返回奖金数。
示例4: 显示工资最高的员工的名字和工作岗位。

除了上面的方式外,还可以使用子查询的方式:

示例5: 显示工资高于平均工资的员工信息。

示例6: 显示每个部门的平均工资和最高工资。
将每个部门分为一个组进行聚合统计最高工资和平均工资。

示例7: 显示平均工资低于2000的部门号和它的平均工资。
分组查询每个部门的平均工资筛选出平均工资小于2000的。

示例8: 显示每种岗位的雇员总数,平均工资。
分组查询岗位的雇员总数,平均工资。

2. 多表查询
实际开发中往往数据来自不同的表,所以需要多表查询。
- 多表查询本质是将多个表中的数据进行穷举组合的结果,这个穷举组合的过程也叫做笛卡尔积运算。
- 在进行多表查询时,只需要将多张表的表名依次放到from子句之后,用逗号隔开即可,这时MySQL将会对给定的这多张表取笛卡尔积,作为多表查询的初始数据源。
我们来看以下示例:
示例1: 显示雇员名、雇员工资以及所在部门的名字。
因为上面的数据来自员工和部门表,因此要多表联合查询。
首先,我们先查看两个表中的数据:

然后,我们尝试查询时带上这两个表:

以姓名为SMITH的数据为例观察:

我们可以发现在两张表联合查询得到的结果中,表中姓名为SMITH的数据是由emp表中姓名为SMITH的数据与dept表中的所有数据结合得来的。此外两张表联合查询得到的结果中所有数据都是这样得来的。这本质是将两个表中的数据进行穷举组合的结果,这个穷举组合的过程也叫做笛卡尔积。

由两张表联合查询得到的结果可以看作一张新表,我们对这张新表加上约束条件,比如只保留emp表中deptno等于dept表中deptno的数据,得到的结果就是将emp中对应的数据与dept表中对应数据结合的表。
仍以姓名为SMITH的数据为例观察:

得到的结果是SMITH在emp表中的信息和对应的部门名和部门地点的表。
我们用这种方式来显示雇员名、雇员工资以及所在部门的名字:

示例2: 显示部门号为10的部门名,员工名和工资。

示例3: 显示各个员工的姓名,工资,及工资级别。
姓名,工资在emp中而工资级别在salgrade表中,因此需要将两个表联合查询,然后由于每个工资级别的工资范围不一样,因此采用emp表中员工在某个工资范围作为筛选条件,可以得到对应员工工资,对应工资等级的结果。
首先,两张表直接联合查询的结果:

然后,对两个表联合查询的结果进行筛选,筛选出工资符合自身等级的:

3. 自连接
自连接是指在同一张表连接查询。
-
自连接将一张表和自己进行笛卡儿积运算。
-
自连接需要在from中对表重命名。
-
from的重命名SQL语句的后续操作都能使用。
将salgrade表自连接:

示例: 显示员工FORD的上级领导的编号和姓名(mgr是员工领导的编号–empno)。
首先将emp表进行自连接,也就是将emp表和emp表进行笛卡尔积运算:

在自连接时,将表分别重命名为了e1,e2,当e1表中的某人的编号等于e2表中FORD领导的编号,即是我们想要的数据:


4. 子查询
子查询是指嵌入在其他sql语句中的select语句,也叫嵌套查询。
4.1 单行子查询
返回一行记录的子查询。
示例: 显示SMITH同一部门的员工。
查询SMITH员工的部门号作为条件筛选员工。

4.2 多行子查询
返回多行记录的子查询。
- in关键字, 数据在集合中,in关键字返回真,否则返回假。
- all 关键字,表示集合内的所有数据。
- any关键字,表示集合内的任意一个数据。
示例: 查询和10号部门的工作岗位相同的雇员的名字,岗位,工资,部门号,但是不包含10自己的。
首先,查看10号部门的工作岗位表:

然后,查找人员中筛选出工作岗位在10号部门的工作岗位表中的,然后去除部门号为10的人员:

示例: 显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号。
首先,查看部门30的所有员工的工资表:

然后,查询比部门30的所有员工的工资表中工资都高的的员工的姓名、工资和部门号:

示例: 显示工资比部门30的任意员工的工资高的员工的姓名、工资和部门号(包含自己部门 的员工)。
首先,查看部门30的所有员工的工资表:

然后,查询比部门30的所有员工的工资表中任意一个员工工资高的的员工的姓名、工资和部门号:

4.3 多列子查询
多列子查询则是指查询返回多个列数据的子查询语句。
-
多列子查询在比较多列数据时需要将待比较的多个列用圆括号括起来。
-
多列子查询同样能使用in,all,any关键字。
示例: 查询和SMITH的部门和岗位完全相同的所有雇员,不含SMITH本人。
查询SIMTH的部门和工作岗位,在emp表中寻找和其相同的,然后去除SIMTH:

将上面的=换成in就变成了多行多列子查询:

4.4 在from子句中使用子查询
子查询语句出现在from子句中。
- 子查询语句出现from子句中,其查询结果将会被当作一个临时表使用。
- from中的子查询出来的临时表必须重命名。
示例1: 显示每个高于自己部门平均工资的员工的姓名、部门、工资、平均工资。
查看各部门的平均工资表:

然后,将员工表和各部门的各部门的平均工资表进行笛卡尔积运算:

最后,将员工表和各部门的平均工资表进行笛卡尔积运算后的结果筛选出部门号相同并且工资高于平均工资,显示每个高于自己部门平均工资的员工的姓名、部门、工资、平均工资。:

示例2: 显示每个高于自己部门平均工资的员工的姓名、部门、工资、平均工资、部门工作位置。
该示例是在上一个示例中加了显示部门工作位置的条件,因此还需要和部门表进行联合查询,然后筛选出部门号相同的:

示例3: 查找每个部门工资最高的人的姓名、工资、部门、最高工资。
首先,查看各部门最高工资表:

然后,查看员工表和各部门最高工资表进行的笛卡尔积运算:

最后,将员工表和各部门最高工资表进行的笛卡尔积运算得到的结果进行条件筛选,筛选的条件是部门号相同,工资相同,显示每个部门工资最高的人的姓名、工资、部门、最高工资:

示例4: 显示每个部门的信息(部门名,编号,地址)和人员数量。
方式1: 使用子查询多表。
首先查看各组人数表:

然后将各组人数表和部门表进行笛卡尔积运算,然后筛选出各组人数表和部门表中部门号相同的:

方式2: 直接多表联合查询并且分组筛选。
首先,查看职员表和员工表笛卡尔积的结果:

然后,对部门表和员工表笛卡尔积的结果进行筛选,筛选出部门编号相同的:

然后将对部门表和员工表笛卡尔积的结果,筛选出部门编号相同的表按部门表的名字、部门号、工作地点进行分组,然后显示出每个部门的信息(部门名,编号,地址)和人员数量,其中按部门表的名字、部门号、工作地点三种属性分组只是因为只有group by中的属性才能显示。

4.5 合并查询
为了合并多个select的执行结果,可以使用集合操作符 union,union all。
- 合并查询中,要合并的几个表必须列个数相同,列属性,列属性顺序可以不同。
union操作符:
该操作符用于取得两个结果集的并集。当使用该操作符时,会自动去掉结果集中的重复行。
union all操作符:
该操作符用于取得两个结果集的并集。当使用该操作符时,不会去掉结果集中的重复行。
示例: 将工资大于2500或职位是MANAGER的人找出来。
首先,查看工资大于2500的人员表和职位是MANAGER的人员表:

然后,分别用union和union all操作符合并大于2500的人员表和职位是MANAGER的人员表:

合并的两个表,列属性相同并且列个数相同,属性列顺序不同:

[MySQL]深入理解复合查询:从基础到进阶
本文介绍了MySQL中的复合查询,包括基本查询回顾,如单行、多行、多列子查询的使用,以及在FROM子句中的应用。重点讲解了多表查询,自连接的概念,并通过实例展示了如何在不同场景下有效地进行数据检索。此外,还讨论了如何合并查询结果,使用UNION和UNIONALL操作符。这些内容对于理解和优化数据库查询至关重要。
4739





