5. 关联查询(多表查询)《重点掌握》
5.1 概念:
有的时候,我们的业务需求的数据不只是在一张表中,而是在两张或两张以上的表中,而这些表中通常都会存
在着"有关系"的字段。那么此时的查询操作涉及到多表查询,我们称之为关联查询。
案例:最简单的关联查询
select * from emp,dept;
select * from emp join dept;
5.2 写法分类
在进行多表关联查询时,通常有两种写法:
-第一种是在from子句中,直接写多个表名,表名之间使用逗号分隔开,如:
select A.*,B.*,C.* from A,B,C where 关联条件
-第二种是在from子句中,多个表名之间使用join关键字连接,并在on关键字后面添加关联条件,此时where和on等价。
select A.*,B.*,C.* from A join B on 关联条件
select a.*,b.*,c.* from A join B on AB 关联条件 join C on AC 或 BC 关联条件
select a.*,b.*,c.* from A join B join C on AB 的关联条件 and BC 或 AC 关联条件
5.3 笛卡尔积
-当做关联查询时,如果两张表中不存在关联字段,或者忘记写关联条件。那么会出现如下图所示的结果。
-即表A中的每一条记录都回与表B中的所有记录进行匹配组合。
例如表A中有m条记录。表B中有N条件。那么 匹配组合的记录数目为M*N,此值被称之为笛卡儿积。
-通常没有意义。
5.4 等值查询
在做关联查询时,使用有关系的字段进行等值条件的限制操作。我们称之为等值查询。
select A.*,B.* from A,B where A.colName=B.colName;
5.5 join连接分类
join关联查询操作分为两大类:内连接和外连接,而外连接有细分为三种类型。参考下图
1.内连接: [inner] join
2.外连接(outer join):(引出一个驱动表的概念:驱动表里的数据全部显示)
-左外连接:left [outer] join,左表是驱动表
-右外连接:right [outer] join,右表是驱动表
-全外连接:full [outer] join, mysql不支持.两张表里的数据全部显示出来
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kgxFgTuU-1587780363559)(C:\Users\陈永豪\AppData\Roaming\Typora\typora-user-images\image-20200323230140138.png)]
内链接
语法:
from tableName1 [inner] join tableName2 on条件
注意:与等值查询的效果是一样的。
外连接
语法:
-左外连接
from tableNamel left join tableName2 on 条件
-右外连接
from tableNamel right join tableName2 on 条件
-全外连接
from tableNamel full [outer] join tableName2 on 条件
外连接的两张表分为驱动表和从动表。驱动表的数据都显示,从动表的数据只显示满足条件的数据。
- 左外连接左边的表就是主表。
- 右外连接右边的表是主表。
5.6 集合查询
union(去重)/union all(不去重):
- 两个查询语句使用上述的关键字连接即可。
- 两个查询语句的字段名,字段个数,类型必须对应上,字段顺序尽可能一致,否则没有意义。
5.7 关联查询的说明
- 多个表用逗号分开,使用where进行条件关联
- 多个表用join连接,使用on进行条件关联
- 笛卡儿积一般无意义。
- 等值连接和内连接效果完全一致。
- 所谓自连接就是连接条件在自己表内。
6. 高级关联查询(子查询)《重点掌握》
6.1 简介
有的时候,**当一个查询语句A所需要的数据,不是直观在表中体现,而是由另外一个查询语句B查询出来的结果,那么查询语句A就是主查询语句,查询语句B就是子查询语句。**这种查询我们称之为高级关联查询,也叫做子查询。
子查询语句的返回数据形式:
- 返回单行单列
- 返回多行单列
- 返回单行多列
- 返回多行多列
子查询语句的位置可以在以下几个子句中
- 在where子句中: 子查询的结果可用作条件筛选时使用的值。
- 在from子句中: 子查询的结果可充当一张表或视图,需要使用表别名。
- 在having子句中: 子查询的结果可用作分组查询再次条件过滤时使用的值
- 在select子句中: 子查询的结果可充当一个字段。仅限子查询返回单行单列的情况。
6.2 在where子句中
# 需求:查询工资大于员工编号为7369这个员工的所有员工信息。
解析:
第一步:目的是查询工资大于某一个数num的所有员工信息
select * from emp where sal>num
第二步:num的值7369员工的工资
select sal from emp where empno = 7369;
第三步:将主查询中的代词使用子查询语句替换
select * from emp where sal>(select sal from emp where empno = 7369);
# 需求:查询工资大于10号部门的平均工资的所有员工信息
select * from emp where sal>(select avg(ifnull(sal,0)) from emp where deptno=10);
# 需求:查询工资大于10号部门的平均工资的非10号部门的员工信息。
select * from emp where sal>(select avg(ifnull(sal,0)) from emp where deptno=10) and deptno<>10;
# 需求:查询与7369同部门的同事信息。
select * from emp where deptno=(select deptno from emp where empno=7369) and empno<>7369;
6.3 在from子句中
# 需求:查询员工的姓名,工资,及其部门的平均工资。
解析:
第一步:先查询每个部门的平均工资
select deptno,avg(ifnull(sal,0)) from emp group by deptno;
第二步:将上一个查询语句的返回结果当成一张表,与员工表进行关联查询
select A.ename,A.sal,B.avg_sal
from emp A join (select deptno,avg(ifnull(sal,0)) avg_sal from emp group by
deptno) B on A.deptno = B.deptno
6.4 在having子句中
# 需求:查询平均工资大于30号部门的平均工资的部门号,和平均工资
select deptno,avg(ifnull(sal,0)) from emp group by deptno having
avg(ifnull(sal,0))>
(select avg(ifnull(sal,0)) from emp where deptno=30);
6.5 在select子句中
相当于外连接的另外一种写法
# 查询每个员工的信息及其部门的平均工资,工资之和,部门人数
select A.empno,A.ename,A.sal,
(select avg(ifnull(sal,0)) from emp B where B.deptno=A.deptno) avg_sal,
(select sum(sal) from emp C where C.deptno=A.deptno) sum_sal,
(select count(*) from emp D where D.deptno=A.deptno) count_
from emp A;