MySQL中的多表连接查询
多表连接分为交叉连接,内连接,外连接,自连接。
连接条件分为等值连接,非等值连接(区别就是连接符号是否是“=”)
学生表:
id | name | classId |
---|---|---|
1 | yang | 1 |
2 | wu | 2 |
3 | li | 2 |
班级表:
classId | className |
---|---|
1 | 计算机 |
2 | 网络 |
3 | 软件 |
交叉连接(cross join)
交叉连接就是两个表中数据的笛卡尔积,假设A表中有m条数据,B表中有n条数据,那么交叉连接之后的表有mn条数据,mn就是笛卡尔积的结果,也就是A表中的每条数据(m)都对应B表中的所有数据(n)。交叉连接(笛卡尔积表)得到的表是内连接、外连接、自连接的中间表,后三种连接方式都是从交叉连接(笛卡尔积表)的表中用限制条件筛选出来的结果。
标准语句:
select * from A cross join B;
等效语句:
select * from A join B;
select * from A,B;
select * from student join class;
id | name | classId | classId | className |
---|---|---|---|---|
1 | yang | 1 | 1 | 计算机 |
2 | wu | 2 | 1 | 计算机 |
3 | li | 2 | 1 | 计算机 |
1 | yang | 1 | 2 | 网络 |
2 | wu | 2 | 2 | 网络 |
3 | li | 2 | 2 | 网络 |
1 | yang | 1 | 3 | 软件 |
2 | wu | 2 | 3 | 软件 |
3 | li | 2 | 3 | 软件 |
内连接(inner join)
标准语句(inner可去掉):
select * from A [inner] join on A.id = B.id;
如果A,B表中连接的属性组相同,且结果中去掉重复的列,可以用using,如下:
select * fromA join using(id);
select * from student join class using(classId);(连接属性组相同且去重)
classId | id | name | className |
---|---|---|---|
1 | 1 | yang | 计算机 |
2 | 2 | wu | 网络 |
2 | 3 | li | 网络 |
用如下语句得到和上面相同的结果
select \* from student natural join class;(连接属性组相同且去重)
那么natural join和join using 的区别是什么?
上面说了,连接条件分为等值连接和非等值连接,natural join 和join using都是特殊的等值连接,都要求A、B表中必须有相同的属性组(等值连接不需要),并在结果中去掉重复的属性组(等值连接不去掉)。
natural join 是根据A、B表中所有共同的属性自动连接。
join using 是根据指定的属性组连接。
显而易见,当join using 指定的属性组是A,B表中所有共同的属性,那么join using 和natural join就有相同的效果。
外连接(outer join)
内连接中连接的属性组只在一个表中存在数据时舍弃,该元组称为悬浮元组,如果需要保留悬浮元组,就用到外连接,外连接分为左外连接(left join)和右外连接(right join),左外连接保留join左侧表中的悬浮元组,右外连接保留join右侧表中的悬浮元组。
左外连接:
select * from A left join B on A.id = B.id;
select * from A left join B using(id);(相同属性组去重)
select * from student left join class using(classid);
classId | id | name | className |
---|---|---|---|
1 | 1 | yang | 计算机 |
2 | 2 | wu | 网络 |
2 | 3 | li | 网络 |
右外连接:
select * from A right join B on A.id = B.id
select * from A right join B using(id);(相同属性组去重)
select * from student right join class using(classid);
classId | className | id | name |
---|---|---|---|
1 | 计算机 | 1 | yang |
2 | 网络 | 2 | wu |
2 | 网络 | 3 | li |
3 | 软件 | null | null |
自连接
自连接一定要给表定义一个别名,否则会出错,定义别名可以用
[表名 别名] 或者 [表名 as 别名]。
select * from A a join A b on a.id = b.otherId;
select * from student as s join student as ss on s.id = ss.classid;
id | name | class Id | id | name | classId |
---|---|---|---|---|---|
1 | yang | 1 | 1 | yang | 1 |
2 | wu | 2 | 2 | wu | 2 |
2 | wu | 2 | 3 | li | 2 |