![020997364b8dd42584464d1ccf0cef0c.png](https://img-blog.csdnimg.cn/img_convert/020997364b8dd42584464d1ccf0cef0c.png)
1. Join 从句
1.1 Inner Join
![9c459778cc78d497ee6fd1176bb1188d.png](https://img-blog.csdnimg.cn/img_convert/9c459778cc78d497ee6fd1176bb1188d.png)
Inner Join 就是 Join。语句为:Join … on。
当连接的列名相同时,可以使用 using 语句。
1.1.1 自然连接
natural join = inner join + using.
1.1.2 Self-join
自连接是 Join 的特例,是自己连接自己。
1.2 Outer Join
Outer Join:保留为匹配的列。Outer 可省略。
1.2.1 Left Outer Join
Left Join 等于 Left Outer Join。
当连接的列名相同时,可以使用 using 语句。
![5626d84e6455c2a6be05255eeea94d20.png](https://img-blog.csdnimg.cn/img_convert/5626d84e6455c2a6be05255eeea94d20.png)
1.2.2 Right Outer Join
Right Join 等于 Right Outer Join。
当连接的列名相同时,可以使用 using 语句。
![cb76d9604c7e35306e3c55aea3e498a1.png](https://img-blog.csdnimg.cn/img_convert/cb76d9604c7e35306e3c55aea3e498a1.png)
1.2.3 Full Join
![21a77397a2171d8c22c3c7851dac0da7.png](https://img-blog.csdnimg.cn/img_convert/21a77397a2171d8c22c3c7851dac0da7.png)
1.2.3.1 MySQL 不支持 Full Join
解决办法:
![dd364b02fbb536dcb7ee54113cb3178d.png](https://img-blog.csdnimg.cn/img_convert/dd364b02fbb536dcb7ee54113cb3178d.png)
1.3 Cross Join
没有 on 关键词。
![0598aa71e0b28007e541a6a7f0cb9c93.png](https://img-blog.csdnimg.cn/img_convert/0598aa71e0b28007e541a6a7f0cb9c93.png)
select a.col1, b.col1 from user1 a cross join user2 b;
1.4 Union 与 Union All
union 拼接多个 select 的结果。去重。
union all 拼接多个 select 的结果。不去重。
1.5 与 Join 相关的 SQL 技巧
1.5.1 更新自身表
需求:
把同时存在于取经四人组和悟空兄弟表中的记录的人在取经四人组表中的over字段更新为“齐天大圣”。
update user1
set over='齐天大圣'
where user1.user_name in (
select b.user_name from user1 a
join user2 b on a.user_name = b.user_name
);
但上面语句不能在 MySQL 中使用,MySQL 不支持。
解决办法:
update user1 a join (
select b.user_name from user1 a join user2 b
on a.user_name = b.user_name) b
on a.user_name = b.username
set over='齐天大圣';
1.5.2 使用 Join 优化子查询
需求:
显示同时存在于取经四人组和悟空兄弟表中的记录。
select a.user_name, a.over, (
select over from user2 b
where a.user_name = b.user_name
) as over2
from user1 a;
优化后:
select a.user_name, a.over, b.over as over2
from user1 a
left join user2 b on a.user_name = b.user_name;
1.5.3 使用 Join 优化聚合子查询
引入一张新的表:
![de3a5c1d20b7dd58970dad424aeddd6c.png](https://img-blog.csdnimg.cn/img_convert/de3a5c1d20b7dd58970dad424aeddd6c.png)
问题:如何查询出四人组中打怪最多的日期?
select a.user_name, b.timestr, b.kills
from user1 a join user_kills b on a.id = b.user_id
where b.kills = (
select max(c.kills) from user_kills c where c.user_id = b.user_id
)
优化:避免子查询。
这里使用了 having 子句进行过滤数据。
select a.user_name, b.timestr, b.kills
from user1 a
join user_kills b on a.id = b.user_id
join user_kills c on c.user_id = b.user_id
group by a.user_name, b.timestr, b.kills
having b.kills = max(c.kills);
1.5.4 如何实现分组选择?
场景:查询每个人打妖怪最多的前两天;