数据库:详细的解释和具体的例子来理解左连接(LEFT JOIN)、右连接(RIGHT JOIN)、内连接(INNER JOIN)以及外连接(FULL JOIN)的概念及其应用场景。
INNER JOIN:只返回两个表中都存在的相关数据。LEFT JOIN:返回左表的所有数据及右表中匹配的数据,右表无匹配则为NULL。RIGHT JOIN:返回右表的所有数据及左表中匹配的数据,左表无匹配则为NULL。FULL JOIN:返回两个表中的所有数据,匹配的和不匹配的都包括,缺失部分用NULL填充。需要所有左表数据,无论右表是否有匹配 → LEFT JOIN需要所有右表数
基本概念
在关系型数据库中,表与表之间通常通过某些共同的字段(如主键和外键)关联起来。连接(JOIN)操作就是基于这些关联字段,将两个或多个表中的数据组合在一起。
1. 内连接(INNER JOIN)
概念:
- 只返回两个表中匹配的记录。
- 如果某一行在任一表中没有匹配项,则该行不会出现在结果集中。
使用场景:
- 当你只关心两个表中都存在的相关数据时使用。
- 例如,查找所有有订单的客户。
示例:
假设有两个表:
-
**
customers
**(客户表)id name 1 Alice 2 Bob 3 Charlie -
**
orders
**(订单表)id customer_id amount 101 1 500 102 1 300 103 2 400
查询:
sql
SELECT customers.name, orders.amount
FROM customers
INNER JOIN orders ON customers.id = orders.customer_id;
结果:
name | amount |
---|---|
Alice | 500 |
Alice | 300 |
Bob | 400 |
解释:
- 只有
customers
表中 ID 为 1 和 2 的客户在orders
表中有对应的订单,因此只有这些记录出现在结果中。 - Charlie 没有订单,所以不出现在结果中。
2. 左连接(LEFT JOIN 或 LEFT OUTER JOIN)
概念:
- 返回左表中的所有记录,以及右表中匹配的记录。
- 如果右表中没有匹配项,则结果中对应的右表字段为
NULL
。
使用场景:
- 当你需要保留左表中的所有数据,即使右表中没有对应的数据时使用。
- 例如,列出所有客户及其订单(包括没有订单的客户)。
示例:
使用上面的 customers
和 orders
表。
查询:
sql
SELECT customers.name, orders.amount
FROM customers
LEFT JOIN orders ON customers.id = orders.customer_id;
结果:
name | amount |
---|---|
Alice | 500 |
Alice | 300 |
Bob | 400 |
Charlie | NULL |
解释:
- Alice 和 Bob 在
orders
表中有对应的订单,因此显示他们的订单金额。 - Charlie 没有订单,因此
amount
字段为NULL
。
3. 右连接(RIGHT JOIN 或 RIGHT OUTER JOIN)
概念:
- 返回右表中的所有记录,以及左表中匹配的记录。
- 如果左表中没有匹配项,则结果中对应的左表字段为
NULL
。
使用场景:
- 当你需要保留右表中的所有数据,即使左表中没有对应的数据时使用。
- 例如,列出所有订单及其客户(包括没有对应客户的订单,这种情况较少见)。
示例:
使用上面的 customers
和 orders
表。
查询:
sql
SELECT customers.name, orders.amount
FROM customers
RIGHT JOIN orders ON customers.id = orders.customer_id;
结果:
name | amount |
---|---|
Alice | 500 |
Alice | 300 |
Bob | 400 |
解释:
- 所有订单都对应有客户,因此结果与内连接类似。
- 如果
orders
表中有订单的客户 ID 在customers
表中不存在,则该订单的name
字段会显示为NULL
。
4. 外连接(FULL JOIN 或 FULL OUTER JOIN)
概念:
- 返回两个表中的所有记录。
- 如果某一表中没有匹配项,则结果中对应的字段为
NULL
。
使用场景:
- 当你需要保留两个表中的所有数据,无论它们是否匹配时使用。
- 例如,列出所有客户和所有订单,无论客户是否有订单,或者订单是否有对应的客户。
注意:
- MySQL 不直接支持
FULL JOIN
,但可以通过组合LEFT JOIN
和RIGHT JOIN
并使用UNION
来实现类似效果。
示例:
使用上面的 customers
和 orders
表。
查询:
sql
SELECT customers.name, orders.amount
FROM customers
LEFT JOIN orders ON customers.id = orders.customer_id
UNION
SELECT customers.name, orders.amount
FROM customers
RIGHT JOIN orders ON customers.id = orders.customer_id;
结果:
name | amount |
---|---|
Alice | 500 |
Alice | 300 |
Bob | 400 |
Charlie | NULL |
解释:
- 由于
orders
表中的所有订单都对应有客户,因此FULL JOIN
的结果与LEFT JOIN
类似。 - 如果有订单没有对应的客户,或者有客户没有订单,这些记录都会出现在结果中,缺失的部分用
NULL
填充。
实际应用中的选择
-
INNER JOIN:
- 当你只关心两个表中都存在的数据时使用。
- 例如,查找有订单的客户。
-
LEFT JOIN:
- 当你需要保留左表中的所有数据,即使右表中没有对应的数据时使用。
- 例如,列出所有员工及其部门信息,包括那些没有分配部门的员工。
-
RIGHT JOIN:
- 当你需要保留右表中的所有数据,即使左表中没有对应的数据时使用。
- 例如,列出所有部门及其员工,包括那些没有员工的部门(这种情况较少见)。
-
FULL JOIN:
- 当你需要保留两个表中的所有数据,无论它们是否匹配时使用。
- 例如,列出所有客户和所有订单,无论是否有对应关系。
更多示例
假设有以下两个表:
-
**
departments
**(部门表)dept_id dept_name 1 人力资源部 2 市场部 3 技术部 -
**
employees
**(员工表)emp_id emp_name dept_id 101 Alice 1 102 Bob 2 103 Charlie 2 104 David 3
使用 LEFT JOIN 查找所有部门及其员工
查询:
sql
SELECT departments.dept_name, employees.emp_name
FROM departments
LEFT JOIN employees ON departments.dept_id = employees.dept_id;
结果:
dept_name | emp_name |
---|---|
人力资源部 | Alice |
市场部 | Bob |
市场部 | Charlie |
技术部 | David |
注意:如果某个部门没有员工,emp_name
将为 NULL
。
使用 RIGHT JOIN 查找所有员工及其部门
查询:
sql
SELECT departments.dept_name, employees.emp_name
FROM departments
RIGHT JOIN employees ON departments.dept_id = employees.dept_id;
结果:
dept_name | emp_name |
---|---|
人力资源部 | Alice |
市场部 | Bob |
市场部 | Charlie |
技术部 | David |
解释:由于所有员工都有对应的部门,结果与内连接类似。
使用 FULL JOIN 查找所有部门和员工
查询(在 MySQL 中需要使用 UNION 实现):
sql
SELECT departments.dept_name, employees.emp_name
FROM departments
LEFT JOIN employees ON departments.dept_id = employees.dept_id
UNION
SELECT departments.dept_name, employees.emp_name
FROM departments
RIGHT JOIN employees ON departments.dept_id = employees.dept_id;
结果:
dept_name | emp_name |
---|---|
人力资源部 | Alice |
市场部 | Bob |
市场部 | Charlie |
技术部 | David |
注意:在当前数据中,所有部门和员工都有对应关系,因此 FULL JOIN
的效果与 INNER JOIN
类似。如果某些部门没有员工,或某些员工没有部门,这些记录将会出现在结果中,缺失的部分用 NULL
填充。
总结
- INNER JOIN:只返回两个表中都存在的相关数据。
- LEFT JOIN:返回左表的所有数据及右表中匹配的数据,右表无匹配则为
NULL
。 - RIGHT JOIN:返回右表的所有数据及左表中匹配的数据,左表无匹配则为
NULL
。 - FULL JOIN:返回两个表中的所有数据,匹配的和不匹配的都包括,缺失部分用
NULL
填充。
选择哪种连接类型取决于你的具体需求:
- 需要所有左表数据,无论右表是否有匹配 → LEFT JOIN
- 需要所有右表数据,无论左表是否有匹配 → RIGHT JOIN
- 只需要两个表中都有的数据 → INNER JOIN
- 需要两个表中的所有数据,无论是否有匹配 → FULL JOIN(在 MySQL 中需用
UNION
实现)
另一个小练习
假设有以下两个表:
-
**
students
**(学生表)student_id name 1 小明 2 小红 3 小刚 -
**
scores
**(成绩表)score_id student_id score 101 1 85 102 1 90 103 2 78
查询所有学生及其成绩(包括没有成绩的学生)
查询:
sql
SELECT students.name, scores.score
FROM students
LEFT JOIN scores ON students.student_id = scores.student_id;
结果:
name | score |
---|---|
小明 | 85 |
小明 | 90 |
小红 | 78 |
小刚 | NULL |
解释:
- 小明有两个成绩,小红有一个成绩,小刚没有成绩,因此
score
为NULL
。

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐
所有评论(0)