一、概述
数据库设计时,根据业务、模块的相互联系,数据库的表之间叶存在着各种各样的联系,他们的关系可以是:
1)一对多(多对一)
2)多对多
3)一对一
二、 多表关系
1)一对多(多对一)
在多的一方建立外键,指向一的主键。
2)多对多
建立中间表,中间表至少包含两个外键,分别关联两个主键。
3)一对一
在任意一方加入外键,关联到另一方的主键,并且设置外键为唯一(UNIQUE)
三、笛卡尔积现象。
select * from t1,t2; (t1、t2表示表1、表2)
使用以上方式会查出t1、t2的所有组合情况(而一般多表查询是需要消除这种无效的笛卡尔积)
可加上where条件消除:
select * from t1,t2 where t1.id = t2.id;
四、多表查询分类
- 连接查询
内连接:查询t1、t2的交集部分数据。
隐式内连接:
select 字段列表 from 表1,表2 where 条件 …;
显式内连接:
select 字段列表 from 表1 [inner] join 表2 on 连接条件 …;
外连接:
左外连接:查询左表所有数据,以及两张表的交集部分数据。
select 字段列表 from 表1 left [outer] join 表2 on 条件;
右外连接:查询右表所有数据,以及两张表的交集部分数据。
select 字段列表 from 表1 right [outer] join 表2 on 条件;
自连接:当前表与自身的连接查询,自连接必须使用表别名,要求两个关系表中进行比较的必须是相同的属性列。
select 字段列表 from 表1 别名1 join 表2 别名2 on 条件 …; - 联合查询
对于union查询,就是把多次查询的结果合并起来,形成一个新的查询结果集。
注意:查询结果集列数、类型需要一样才能合并,[all]参数不去重,不带[all]去重。
select 字段列表 from 表1 ...
union [all]
select 字段列表 from 表2 ...;
- 子查询
子查询也叫嵌套查询。
语法:
select * from t1 where cloumn1 = (select cloumn1 from t2);
子查询外部语句可以是insert/update/delete/select中任意一个。
按结果不同可以分为:
①标量子查询(子查询结果为单个)
②列子查询(子查询结果为一列,可以是多行)
③行子查询(子查询结果为一行)
④表子查询(子查询结果为多行多列)
按子查询位置,分为:where之后、from之后、select之后;
1)标量子查询
select * from t1 where xx_id = (select id from t2 where name = “人事部”)
select * from t1 where age > (select age from t2 where stu_id = 001);
2) 列子查询
常用操作符:
IN:在指定集合范围内,多选一。
NOT IN:不在指定集合范围内。
ANY:子查询返回列表中,有一个满足即可。
SOME:与any等同,使用SOME的地方都可以使用ANY
ALL:子查询返回列表的所有值都必须满足。
根据ID查询:
select * from emp where dept_id in (select id from dept where name = “人事部” or “财务部”)
比所有都高:
select * from emp where salary > all (select salary from emp where dept_id = (select id from dept where name = “财务部”))
比任意一人都高,some效果一样:
select * from emp where salary > any (select salary from emp where dept_id = (select id from dept where name = “财务部”))
3) 行子查询
select * from emp where (salary,managerid) = (select salary,managerid from emp where name = “小美”)
4) 表子查询
查询职位、薪资相同的案例:
select * from emp where (job,salary) in (select job,salary from emp where name =“zhangsan” or name =“lisi”)
子查询用在from之后:
select e.*,d.* from (select * from emp where entrydata > ‘2021-01-01’) e left join dept d on e.dept_id = d.id;