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子句中指明筛选条件为员工的部门号等于临时表中的部门号即可。如下:
