MySQL 查询进阶指南:子查询、多表连接与 UNION 操作全解析
前面我们讲解的mysql表的查询都是对一张表进行查询,在实际开发中这远远不够。
基本查询回顾与 子查询
- 查询工资高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为大写的J
- 按照部门号升序而雇员的工资降序排序
- 使用年薪进行降序排序
注意事项:
年薪的结构体系时月薪*12 + 奖金,但是如果某个职位的奖金没有奖金,那么奖金列为空,这和有奖金但是奖金是0是不一样的,null 是不参与运算的。
这里进行处理的时候使用ifnull函数将null当作0进行处理,避免null不参与运算导致的结果不准确。
- 显示工资最高的员工的名字和工作岗位
- 显示工资高于平均工资的员工信息
- 显示每个部门的平均工资和最高工资
- 显示平均工资低于2000的部门号和它的平均工资
- 显示每种岗位的雇员总数,平均工资
多表查询
实际开发中往往数据来自不同的表,所以需要多表查询。本节我们用一个简单的公司管理系统,有三张 表EMP,DEPT,SALGRADE来演示如何进行多表查询。
例如,有一个这样的查询要求:显示雇员名、雇员工资以及所在部门的名字
因为上面的数据来自EMP和DEPT表,因此要联合查询
所谓的联合查询就是将两张表进行拼接起来,进行拼接是采用如上图所示的暴力枚举进行的
select * from 表1,表2
但是进行暴力拼接的很多信息都是没有用的,例如部门号不同的信息组合到了一起,我们需要进行筛选出来部门号一致的有效信息。
最后将所需要的信息进行挑选出来即可
- 显示部门号为10,员工名和工资
- 显示各个员工的姓名,工资,及工资级别
自连接
既然两个不同的表可以进行做笛卡尔积,那么 一张表能不能做笛卡尔积呢??
直接进行是不可以的,但是可以先进行重命名然后在进行做笛卡尔积,这种行为称为自连接
什么样的场景需要进行自连接呢??
- 显示员工FORD的上级领导的编号和姓名(mgr是员工领导的编号--empno)
首先说明一下为什么要在这种情况下使用自连接,要想进行查找员工的领导,需要从emp表中进行查找领导的编号,但是呢领导也是属于员工的,先通过该表进行查找到领导的员工号,再通过该员工号进行查找对应的信息。
既可以使用自连接的方式进行查找
-- 使用到表的别名 --from emp leader, emp worker,给自己的表起别名,因为要先做笛卡尔积,所以别名可以先识别
也可以使用子查询的方式进行查找
子查询
子查询与where
子查询是放在
SELECT
、FROM
或WHERE
子句中的一个查询语句,其结果被外层查询使用
单行子查询
查询结果 一行一列
- 显示SMITH同一部门的员工
多行子查询
查询结果只有单列,但是单列中有多行
in 关键字;
在子查询返回的多个值中进行等值匹配
表达式 IN (子查询)
- 查询和10号部门的工作岗位相同的雇员的名字,岗位,工资,部门号,但是不包含10自己的
all 关键字;
当前值必须满足对子查询返回的所有值都成立
表达式 >/=/< ALL (子查询)
- 显示工资比部门30的所有员工的工资高的员工的姓名、工资和部门号
any 关键字;
当前值只需满足对某一个值成立即可
表达式 >/=/< ALL (子查询)
- 显示工资比部门30的任意员工的工资高的员工的姓名、工资和部门号(包含自己部门 的员工)
多列子查询
单行子查询是指子查询只返回单列,单行数据;多行子查询是指返回单列多行数据,都是针对单列而言 的,而多列子查询则是指查询返回多个列数据的子查询语句
查询和SMITH的部门和岗位完全相同的所有雇员,不含SMITH本人
mysql> select ename from EMP where (deptno, job)=(select deptno, job from EMP where
ename='SMITH') and ename <> 'SMITH';
+-------+
| ename |
+-------+
| ADAMS |
+-------+
在from子句中使用子查询
子查询在两个语句中最常用的两个子句,一个是在where 语句中 判断条件,一个是在from语句中 充当笛卡尔积
多表查询的核心指导思想:
解决多表的问题的本质:想办法将多表转化成单表,所以mysql中,所有的select的问题全部都可以转化成单表问题
- 显示每个高于自己部门平均工资的员工的姓名、部门、工资、平均工资
mysql> select ename, deptno, sal, format(asal,2) from emp, -> (select avg(sal) asal, deptno dt from emp group by deptno) tmp-> where emp.sal > tmp.asal and emp.deptno=tmp.dt;
+-------+--------+---------+----------------+
| ename | deptno | sal | format(asal,2) |
+-------+--------+---------+----------------+
| FORD | 20 | 3000.00 | 2,175.00 |
| SCOTT | 20 | 3000.00 | 2,175.00 |
| JONES | 20 | 2975.00 | 2,175.00 |
| BLAKE | 30 | 2850.00 | 1,566.67 |
| ALLEN | 30 | 1600.00 | 1,566.67 |
| KING | 10 | 5000.00 | 2,916.67 |
+-------+--------+---------+----------------+
- 查找每个部门工资最高的人的姓名、工资、部门、最高工资
合并查询
在实际应用中,为了合并对各select 的执行结果,可以使用集合操作符 union ,union all
union
该操作符用于取地两个结果集的并集。当使用该操作符时,会自动去掉结果集中的重复行。
union all
该操作符用于取得两个结果集的并集。当使用该操作符时,不会去掉结果集中的重复行。