开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 6 天,点击查看活动详情
关联查询:两个或更多个表一起查询。
关联查询结果的7种情况
两个表一起查询的前提条件:两表之间必须有关联。即要有相同逻辑意义和数据类型的字段
情况一:A∩B
我们发现,AB两表里都存在部门编号,这就是他们的关联,逻辑意义相同,数据类型也相同
现在要找 A∩B的情况,那就从关联里找相同的,比如说A表中D1001可以对应B表的D1001,那么把AB表的这一行组合在一起就行。最后有个NULL值在B表中无对应,则舍弃。
另外,B表中D1004在A表无对应数据行,直接剔除
情况二:A
这种情况就是A的数据要全保留,仔细看图应该不难发现A∩B组合之后,还剩一个王五那一行在B表中没有对应的关联数据,那就直接写NULL。
情况三:A-A∩B
就是把AB有关联的全剔除,只留下A表中在B表无关联的数据
情况四:B
和情况二是反过来的,仔细看一下情况二,是保留A∩B和A中所有数据,所以B表中无效数据D1004那一行被踢掉。
但这里是保留A∩B和B中所有数据,所以A表中无效数据S1005王五,那一行被踢掉。
情况五:B-A∩B
就是把AB有关联的全剔除,只留下B表中在A表无关联的数据,和情况三相反。
情况六:A∪B
AB的数据全都要
情况七:A∪B-A∩B
取A表没交集的和B表没交集的
两个表的记录分为四种:
①A表中能在B表中找到对应的记录的记录
②A表中在B表中找不到对应的记录的记录
③B表中可以在A表找到对应的记录的记录
④B表中在A表中找不到对应的记录的记录
- A∩B ①③
- A ①②
- A-A∩B ②
- B ③④
- B-A∩B ④
- A∪B ①②③④
- A∪B-A∩B ②④
如何实现7种查询结果
- 内连接 inner join
- 外连接 outer join
- 左外连接 left outer join 或 left join
- 右外连接 right outer join 或 right join
- 全外连接 full outer join 或 full join
注意:MySQL不支持全外连接,它是通过union关键字合并其他的查询结果实现全外连接
下面是几种连接和查询结果的对应关系:
- 内连接 ==> A∩B
- 左连接 ==> A 或 A-A∩B
- 右连接 ==> B 或 B-A∩B
- 全外连接 ==> A∪B 或 A∪B-A∩B
既然MySQL不支持全外连接,其中A∪B通过左连接的A union 右连接的B实现
A∪B-A∩B通过左连接的A-A∩B union 右连接的B-A∩B实现
内连接
#查询员工表的员工姓名,和部门编号,部门表的部门名称
#不显示那些 没有分配部门的员工,也不包括那么没有员工的部门
select ename,t_employee.did,dname -- 两个表中都有did,要指明那个表的did
from t_employee inner join t_department
on t_employee.did = t_department.did -- 要指明按照部门编号进行关联
左连接
语法:
- A表 left join B表 on A表.关联字段 = B表.关联字段(对应A查询结果)
- A表 left join B表 on A表.关联字段 = B表.关联字段 where A表和B表中是从表.关联字段 is null(对应A-A∩B查询结果)
#查询所有的员工姓名和部门编号,部门名称,包括那些没有分配部门的员工
#但不包括没有员工的部门
select ename,t_employee.did,dname
from t_employee left join t_department
on t_employee.did = t_department.did;
#查询所有员工的姓名和部门编号,部门名称,只显示那些没有分配部门的员工
#但不包括没有员工的部门
select ename,t_employee.did,dname
from t_employee left join t_department
on t_employee.did = t_department.did
where t_employee.did is null ;
右连接
语法:
- A表 right join B表 on A表.关联字段 = B表.关联字段(对应B查询结果)
- A表 right join B表 on A表.关联字段 = B表.关联字段 where 从表.关联字段 is null(对应B-A∩B查询结果)
#查询所有部门的编号,部门的名称,以及该部门下所有的员工信息
#包括那些没有员工的部门,不包括没有分配部门的员工
select t_department.did,dname,t_employee.*
from t_employee right join t_department
on t_employee.did = t_department.did;
#查询所有部门的编号,部门的名称,以及该部门下所有的员工信息
#只显示那些没有员工的部门,不包括没有分配部门的员工
select t_department.did,dname,t_employee.*
from t_employee right join t_department
on t_employee.did = t_department.did
where t_employee.did is null ;
/*
部门表是主表,员工表示从表
两个表的关联字段是did(部门编号)
部门表中是所有部门的信息,是完整的部门信息
员工表选择所属部门时,必须参考部门表,选择的部门编号必须在部门表中找得到。
*/
union合并查询结果
语法:
- A∪B:左连接的A union 右连接的B
- A∪B-A∩B:左连接的A-A∩B union 右连接的B-A∩B
# 查询所有员工和所有部门的信息,包括那些没有员工的部门,和没有分配部门的员工
# 也包括有员工的部门,和有部门的员工
select *
from t_employee left join t_department
on t_employee.did = t_department.did
union
select *
from t_employee right join t_department
on t_employee.did = t_department.did;
#查询所有员工和所有部门的信息
#只显示那些没有部门的员工,没有员工的部门
select *
from t_employee left join t_department
on t_employee.did = t_department.did
where t_employee.did is null
union
select *
from t_employee right join t_department
on t_employee.did = t_department.did
where t_employee.did is null ;
特殊的内连接
之前的内连接,我们使用的是A表 inner join B表 on 条件
现在我可以改成不用inner join ,写成A表 , B表 where 条件
#查询员工和部门的信息,只显示有部门的员工和有员工的部门
select *
from t_employee , t_department
where t_employee.did = t_department.did;
更多表关联
职位表和员工表的job_id关联,部门表和员工表的did关联。
需要注意的是:n张表关联,关联条件要编写n-1个。
这里的关联条件有:
- t_employee.did = t_department.did
- t_employee.job_id = t_job.jid
基本语法:A表 inner|left|right join B表 on 关联条件1 inner|left|right join C表 on 关联条件2
#查询每一个员工的姓名,职位名称,部门名称
# 姓名在t_employee,职位在t_job,部门在t_department表中
select ename,jname,dname
from t_employee left join t_department on t_department.did = t_employee.did
left join t_job on t_employee.job_id = t_job.jid;