一、MySQL 连接查询基本语法
SELECT [DISTINCT] 查询列表
FROM table_a AS 别名 [连接类型]
JOIN table_b 别名
ON 连接条件
[WHERE 筛选条件]
[GROUP BY 分组]
[HAVING 分组筛选条件]
[ORDER BY 排序列表]
[LIMIT 分页条件]
二、连接类型分类
1、内连接: INNER JOIN
2、外连接:
左外连接: LEFT [OUTER] JOIN
右外连接: RIGHT [OUTER] JOIN
3、全外连接: FULL [OUTER] JOIN
4、交叉连接: CROSS
三、各种连接查询解释及案例
1、内连接
1.1、INNER JOIN:内连接(查询的是两张表都符合条件的公共部分)
1.2、基本语法
SELECT 查询列表
FROM 表A AS 别名 a
INNER JOIN 表B AS 别名 b
ON 连接条件;
1.3、根据连接条件分类
1、等值连接
2、非等值连接
3、自连接
2、左外连接
2.1、LEFT JOIN:左外连接(查询的是 A 表中有而 B 表中没有的部分 + 两张表的公共部分)
2.2、基本语法
SELECT 查询列表
FROM 表A AS 别名 a
LEFT JOIN 表 B AS 别名 b
ON 连接条件;
2.3、表结构与数据
2.4、具体案例
在执行左连接查询之前,先看看使用内连接查询出来的数据,如下图可以看到查出的是 7 条记录
SELECT g.id,g.name,g.age,g.boyFriend_id,b.id,b.name,b.age
FROM girls AS g
INNER JOIN boys AS b
ON g.boyFriend_id = b.id;
接着以 girls 表作为主表进行左连接查询,如下图可以看到查询的记录是 9 条
SELECT g.id,g.name,g.age,g.boyFriend_id,b.id,b.name,b.age
FROM girls AS g
LEFT JOIN boys AS b
ON g.boyFriend_id = b.id;
其中 1-7 条记录就是 INNER JOIN 查询出来的记录,而第 8 条和第 9 条记录是主表(girls)中存在的记录而从表(boys)中不存在.
得出结论:左连接查询的结果 = 两表的交集部分(INNER JOIN的查询结果) + 主表中存在而从表中不存在的记录
然后接着以 boys 表作为主表进行左连接查询,如下图可以看到查询的记录是 10 条,可以看出 1-7 条记录就是 INNER JOIN 查询出来的记录,而第 8 条第 9 条和第 10 条记录是主表(boys)中存在的记录但是从表(girls)中不存在该记录.
SELECT g.id,g.name,g.age,g.boyFriend_id,b.id,b.name,b.age
FROM girls AS g
INNER JOIN boys AS b
ON g.boyFriend_id = b.id;
得出结论:左连接查询的结果 = 两表的交集部分(INNER JOIN的查询结果) + 主表中存在的记录而从表中不存在的记录
3、右外连接
3.1、RIGHT JOIN:右外连接(查询的是 B 表中有而 A 表中没有的部分 + 两张表公共的部分)
3.2、右外连接和左外连接使用基本相似,可以通过变换主表和从表的位置来达到相同的效果,例如下面的 SQL 的效果是相同的
# 左外连接
SELECT g.id,g.name,g.age,g.boyFriend_id,b.id,b.name,b.age
FROM girls AS g
LEFT JOIN boys AS b
ON g.boyFriend_id = b.id;
# 右外连接
SELECT g.id,g.name,g.age,g.boyFriend_id,b.id,b.name,b.age
FROM boys AS b
RIGHT JOIN girls g
ON g.boyFriend_id = b.id;
4、全(外)连接
FULL (OUTER) JOIN:全连接(查询的是 A 表中存在而 B 表中不存在的记录 + B 表中存在而 A 表中不存在的记录 + A 表和 B 表的交集)
注:Oracle 中有 full join,mysql 中没有 full join,但是我们可以通过 union 或 union all 来实现全连接
4.1、使用 UNION 进行全连接,可以看出数据是去除了重复值
SELECT g.id,g.name,g.age,g.boyFriend_id,b.id,b.name,b.age
FROM girls AS g
LEFT JOIN boys AS b
ON g.boyFriend_id = b.id
UNION
SELECT g.id,g.name,g.age,g.boyFriend_id,b.id,b.name,b.age
FROM boys AS b
LEFT JOIN girls AS g
ON g.boyFriend_id = b.id;
使用 UNION ALL 进行全连接,可以看出数据没有去除了重复值,简单的将 A 表和 B 表合并在一起了
SELECT g.id,g.name,g.age,g.boyFriend_id,b.id,b.name,b.age
FROM girls AS g
LEFT JOIN boys AS b
ON g.boyFriend_id = b.id
UNION ALL
SELECT g.id,g.name,g.age,g.boyFriend_id,b.id,b.name,b.age
FROM boys AS b
LEFT JOIN girls AS g
ON g.boyFriend_id = b.id;
5、其它常用的连接查询形式
5.1、查询出 A 表中存在而 B 表中不存在的记录
SELECT g.id,g.name,g.age,g.boyFriend_id,b.id,b.name,b.age
FROM girls AS g
LEFT JOIN boys AS b
ON g.boyFriend_id = b.id
WHERE b.id IS NULL;
5.2、查询出 B 表中存在而 A 表中不存在的记录
SELECT g.id,g.name,g.age,g.boyFriend_id,b.id,b.name,b.age
FROM boys AS b
LEFT JOIN girls AS g
ON g.boyFriend_id = b.id
WHERE g.boyFriend_id IS NULL;
5.3、查询出 A 表和 B 表去除了交集以后的并集部分
SELECT g.id,g.name,g.age,g.boyFriend_id,b.id,b.name,b.age
FROM girls AS g
LEFT JOIN boys AS b
ON g.boyFriend_id = b.id
WHERE b.id IS NULL
UNION
SELECT g.id,g.name,g.age,g.boyFriend_id,b.id,b.name,b.age
FROM boys AS b
LEFT JOIN girls AS g
ON g.boyFriend_id = b.id
WHERE g.boyFriend_id IS NULL;