4. 多表查询
4. 多表查询
1. 多表关系
- 项目开发中,在进行数据库表结构设计时,会根据业务需求及业务模块之间的关系,分析并设计表结构,由于业务之间相互关联,所以各个表结构之间也存在着各种联系,基本上分为三种:
- 一对多(多对一)
- 多对多
- 一对一
1.1 一对多
- 案例:部门与员工
- 关系:一个部门对应多个员工,一个员工对应一个部门
- 实现:在多的一方建立外键,指向一的一方的主键

1.2 多对多
- 案例:学生与课程
- 关系:一个学生可以选多门课程,一门课程也可以供多个学生选修
- 实现:建立第三张中间表,中间表至少包含两个外键,分别关联两方主键

- 创建三个表
1 | |
1.3 一对一
- 案例:用户与用户详情
- 关系:一对一关系,多用于单表拆分,将一张表的基础字段放在一张表中,其他详情字段放在另一张表中,以提升操作效率
- 实现:在任意一方加入外键,关联另外一方的主键,并且设置外键为唯一的(UNIQUE)

1 | |
2. 查询
2.1 多表查询
从多张表中国查询数据
合并查询(笛卡尔积,会展示所有组合结果):
1
select * from employee, dept;
笛卡尔积:两个集合A集合和B集合的所有组合情况(在多表查询时,需要消除无效的笛卡尔积)
消除无效笛卡尔积,加上条件:
1 | |
2.2 分类
- 连接查询
- 内连接:相当于查询A、B的交集
- 外连接:
- 左外连接:查询左表所有数据,以及两张表交集部分数据
- 右外连接:查询右表所有数据,以及两张表交集部分数据
- 自连接:
- 当前表与自身的连接查询,自连接必须使用表别名
- 子查询
3. 内连接查询
- 内连接查询的是两张表交集的部分
- 隐式内连接:
1 | |
- 显式内连接:
1 | |
- 显式性能比隐式高
例子:
1 | |
1 | |
4. 外连接查询
- 左外连接:
- 查询左表所有数据,以及两张表交集部分数据
- 相当于查询表1的所有数据,包含表1和表2交集部分数据
1 | |
- 右外连接:
- 查询右表所有数据,以及两张表交集部分数据
1 | |
例子:
1 | |
左连接可以查询到没有dept的emp,右连接可以查询到没有emp的dept
5. 自连接查询
- 当前表与自身的连接查询,自连接必须使用表别名
语法:
1 | |
- 自连接查询,可以是内连接查询,也可以是外连接查询
例子:
1 | |
6. 联合查询 union, union all
把多次查询的结果合并,形成一个新的查询集
语法:
1 | |
注意事项
- 对于联合查询的多张表的列数必须保持一致,字段类型也需要保持一致。
- UNION ALL 会有重复结果,UNION 不会
- 联合查询比使用or效率高,不会使索引失效
7. 子查询
SQL语句中嵌套SELECT语句,称谓嵌套查询,又称子查询。
1 | |
子查询外部的语句可以是 INSERT / UPDATE / DELETE / SELECT 的任何一个
根据子查询结果可以分为:
- 标量子查询(子查询结果为单个值)
- 列子查询(子查询结果为一列)
- 行子查询(子查询结果为一行)
- 表子查询(子查询结果为多行多列)
根据子查询位置可分为:
- WHERE 之后
- FROM 之后
- SELECT 之后
7.1 标量子查询
- 子查询返回的结果是单个值(数字、字符串、日期等)。
- 常用操作符:= < > > >= < <=
- 例子:
1 | |
7.2 列子查询
返回的结果是一列(可以是多行)。
常用操作符:
| 操作符 | 描述 |
|---|---|
| IN | 在指定的集合范围内,多选一 |
| NOT IN | 不在指定的集合范围内 |
| ANY | 子查询返回列表中,有任意一个满足即可 |
| SOME | 与ANY等同,使用SOME的地方都可以使用ANY |
| ALL | 子查询返回列表的所有值都必须满足 |
例子:
1 | |
7.3 行子查询
- 返回的结果是一行(可以是多列)。
- 常用操作符:=, <, >, IN, NOT IN
- 例子:
1 | |
7.4 表子查询
- 返回的结果是多行多列
- 常用操作符:IN
- 例子:
1 | |
8. 查询案例
1 | |