教程来源
黑马程序员 MySQL数据库入门到精通,从mysql安装到mysql高级、mysql优化全囊括
多表关系
各个表结构之间存在各种关联关系,基本上分为三种:一对多(多对一)、多对多、一对一
一对多(多对一)
例如:部门与员工的关系。一个部门对应多个员工、一个员工对应一个部门(不考虑一个员工对应多个部门的情况)
实现:在多的一方建立外键,指向一的一方的主键
多对多
例如:学生与课程的关系。一个学生可以选修多门课程,一门课程也可以供多个学生选择
实现:建立第三张中间表,中间表至少包含两个外键,分别关联两份主键
一对一
例如:用户与用户详情的关系。一对一关系多用于单表拆分,将一张表的基础字段放在一张表中,其他详情字段放在另一张表中,以提升操作效率。
比如:提高查询性能,当一张表中数据过多时查询会变得缓慢;可以使数据库结构更清晰,每个表的结构更加简单
可以在任何一方加入外键,关联另一方的主键,并且设置外键为唯一的。
多表查询概述
指从多张表中查询数据。
笛卡尔积
笛卡尔积:指在数学中,两个集合A、B的所有组合情况。在多表查询时需要消除无效的笛卡尔积
分类
-
连接查询
- 内连接:相当于查询A、B交集的部分
- 外连接:
- 左外连接:查询左表所有数据,以及两张表交集部分数据
- 右外连接:查询右表所有数据 ,以及两张表交集部分数据
- 自连接:当前表与自身的连接查询,自连接必须使用表别名
-
子查询
内连接
内连接查询的是两张表交集的部分
隐式内连接
select 字段 from 表1,表2 where 条件
显示内连接
select 字段列表 from 表1 join 表2 on 连接条件
查询员工工号、姓名及所在部门的名称
// 隐式内连接
select emp.workno,emp.name,dept.dept_name from emp,dept where emp.dept_id = dept.id;
// 显示外连接
select emp.workno,emp.name,dept.dept_name from emp join dept on emp.dept_id = dept.id;
外连接
左外连接
select 字段 from 表1 left join 表2 on 条件
查询emp
表的所有数据,和对应的部门信息
select emp.*,dept.dept_name from emp left join dept on emp.dept_id = dept.id;
这里与内连接的区别,假如有一个新员工刚入职还没有对应的部门,内连接是不会查询出该员工的信息,而左外连接会查询到该信息。
内连接是两边都要有;左外连接是左边都要有,右边可以不要有
右外连接
select 字段 from 表1 right join 表2 on 条件
查询dept
的所有数据,和对应的员工表的信息
自连接
select 字段列表 from 表A join 表A 别名B on 条件
自连接查询,可以是内连接查询,也可以是外连接查询。
例如,当表中的数据具有层级结构时,可以使用自连接来查询父子关系或者层级关系。比如,在员工表中查询员工的上级领导或者下属。
自连接可以帮助我们在同一表中进行比较和分析操作,解决一些复杂的查询需求。但是需要注意,在使用自连接时需要谨慎处理好连接条件,避免出现无限循环或者性能问题。
select emp.*,a.name from emp join emp as a where emp.manager_id = a.id ;
联合查询
联合查询就是把多次查询的结果合并起来,形成一个新的查询结果集。比如,查询出薪资低于5000的员工和年龄大于60的员工。
关键字:union all
和 union
,后者是对前者的一个数据去重。
联合查询时多张表的列数必须保持一致、字段类型也需要保持一致。
select 字段列表 from a 条件
union
select 字段列表 from b 条件
子查询
SQL中嵌套select
语句,称为嵌套查询,又称子查询。
select * from t1 where column1 = (select column1 from t2)
子查询的外部语句可以是insert
,delete
,update
,select
中的任何一个
根据子查询的结果,可以分为:
- 标量子查询,子查询结果是单个值
- 列子查询,子查询的结果是一列
- 行子查询,子查询的结果是一行
- 表子查询,子查询的结果为多行多列
标量子查询
子查询返回的结果是单个值(数字、字符串、日期等),这种子查询称为标量子查询。
常用的操作符有:>
,<
,!=
,=
查询出研发中心的所有员工信息:
1)先查询出研发中心的部门id
2)根据部门id查询员工信息
select * from emp where dept_id = (select id from dept where dept_name = '研发中心')
列子查询
子查询返回的结果是一列(可以是多列),这种子查询称为列子查询
常用的操作符有:in
、not in
、and
、some
、all
查询交付中心和研发中心的所有员工信息
1)查询出交付中心和研发中心的部门id
2)根据部门id查询员工信息
select * from emp where dept_id in (select id from dept where dept_name in ('交付中心','研发中心'))
行子查询
子查询返回的结果是一行(可以是多列),这种子查询称为行子查询
常用的操作符有:>
,<
,!=
,=
查询与秦一的性别相同的同部门员工信息
1)查询秦一的性别与部门id
2)根据性别和部门id查询员工信息
select * from emp where (sex ,dept_id) = (select sex ,dept_id from emp where name = '秦一')
表子查询
子查询返回的结果是多行多列,这种子查询称为表子查询
常用操作符:in
查询与秦一、李二的性别和部门相同的员工信息
select * from emp where (sex ,dept_id) in (select sex ,dept_id from emp where name = '秦一' or name = '李二')
查询入职日期是2023-06-12
之后的员工信息,及其部门信息
select e.*,d.* from (select * from emp where entrydata > '2023-06-12') as e
left join dept as d on e.dept_id = d.id