深入理解 SQL 的 7 种 JOIN 操作

在 SQL 中,JOIN 是一个非常重要的操作,它用于连接两个或多个表,从而根据条件返回相关数据。不同类型的 JOIN 有不同的连接方式,根据实际需求可以返回不同的数据集。在本文中,我们将通过 学生表(Students)成绩表(Scores) 的例子,深入了解七种常见的 JOIN 操作,并通过 员工表(Employees)部门表(Departments) 的例子讲解 SELF JOINNATURAL JOIN

学生表(Students)

student_id name department_id
1 Alice 10
2 Bob 20
3 Charlie 10
4 David NULL

成绩表(Scores)

student_id score
1 85
2 90
3 75
5 80

1. INNER JOIN

INNER JOIN 返回两个表中 有匹配的行。如果在一个表中没有匹配的记录,那么这条记录将不会出现在结果中。

SQL 查询

1
2
3
4
SELECT * 
FROM students
INNER JOIN scores
ON students.student_id = scores.student_id;

结果

student_id name department_id student_id score
1 Alice 10 1 85
2 Bob 20 2 90
3 Charlie 10 3 75
  • AliceCharliestudent_id 都在成绩表中有记录,匹配到成绩。Bob 也有成绩记录。
  • David 没有成绩记录,所以没有出现在结果中。

2. LEFT JOIN (LEFT OUTER JOIN)

LEFT JOIN 返回 左表(students) 中的所有行,以及右表(成绩表)中与之匹配的行。如果右表没有匹配的行,右表的列会显示 NULL

SQL 查询

1
2
3
4
SELECT * 
FROM students
LEFT JOIN scores
ON students.student_id = scores.student_id;

结果

student_id name department_id student_id score
1 Alice 10 1 85
2 Bob 20 2 90
3 Charlie 10 3 75
4 David NULL NULL NULL
  • David 没有成绩记录,因此他的成绩为 NULL
  • 其他学生的成绩都正常返回。

3. RIGHT JOIN (RIGHT OUTER JOIN)

RIGHT JOINLEFT JOIN 相似,不过它更关注右表(成绩表),返回右表中的所有行,即使左表没有匹配的行。如果左表没有匹配的行,左表的列会显示 NULL

SQL 查询

1
2
3
4
SELECT * 
FROM students
RIGHT JOIN scores
ON students.student_id = scores.student_id;

结果

student_id name department_id student_id score
1 Alice 10 1 85
2 Bob 20 2 90
3 Charlie 10 3 75
NULL NULL NULL 5 80
  • 结果中包含了右表(成绩表)中的所有记录。
  • NULL 行显示的是成绩表中的一条记录(student_id = 5),但在学生表中没有对应记录。

4. FULL JOIN (FULL OUTER JOIN)

FULL JOIN 返回 左表右表 中的所有行,即使某一表没有匹配的行。如果没有匹配的行,缺少的部分会显示 NULL

SQL 查询

1
2
3
4
SELECT * 
FROM students
FULL JOIN scores
ON students.student_id = scores.student_id;

结果

student_id name department_id student_id score
1 Alice 10 1 85
2 Bob 20 2 90
3 Charlie 10 3 75
4 David NULL NULL NULL
NULL NULL NULL 5 80
  • David 没有成绩记录,因此他的成绩为 NULL
  • 成绩表中 student_id = 5 的记录没有对应的学生,学生名为 NULL

5. CROSS JOIN

CROSS JOIN 返回 左表右表笛卡尔积,即每一行左表与每一行右表的所有可能组合。它没有连接条件,所有行都会组合。

SQL 查询

1
2
3
SELECT * 
FROM students
CROSS JOIN scores;

结果

student_id name department_id student_id score
1 Alice 10 1 85
1 Alice 10 2 90
1 Alice 10 3 75
1 Alice 10 5 80
2 Bob 20 1 85
2 Bob 20 2 90
2 Bob 20 3 75
2 Bob 20 5 80
3 Charlie 10 1 85
3 Charlie 10 2 90
3 Charlie 10 3 75
3 Charlie 10 5 80
4 David NULL 1 85
4 David NULL 2 90
4 David NULL 3 75
4 David NULL 5 80
  • 结果显示了左表(学生表)与右表(成绩表)的每一行组合。
  • 总共生成了 4 个学生 × 4 个成绩 = 16 条记录。

6. SELF JOIN

SELF JOIN 是对同一个表进行连接。我们通过为同一表指定不同的别名,来实现表与自身之间的连接。SELF JOIN 适用于查找表中记录之间的关系,例如员工与经理的关系。

假设我们有一个员工表(Employees):

emp_id name manager_id
1 Alice 3
2 Bob 3
3 Charlie NULL
4 David 2

我们想要查询每个员工的姓名及其经理的姓名。

SQL 查询

1
2
3
4
SELECT * 
FROM employees e1
LEFT JOIN employees e2
ON e1.manager_id = e2.emp_id;

结果

emp_id name manager_id emp_id name manager_id
1 Alice 3 3 Charlie NULL
2 Bob 3 3 Charlie NULL
3 Charlie NULL NULL NULL NULL
4 David 2 2 Bob 3
  • AliceBob 的经理是 Charlie,而 David 的经理是 Bob

7. NATURAL JOIN

NATURAL JOIN 自动根据两个表中 列名相同的列 进行连接。你不需要显式指定连接条件,它会自动查找并使用同名的列。

假设我们有一个员工表(Employees)和部门表(Departments):

员工表(Employees):

emp_id name department_id
1 Alice 10
2 Bob 20
3 Charlie 10
4 David NULL

部门表(Departments):

department_id department_name
10 HR
20 IT

我们希望查询每个员工的姓名及其部门名称。

SQL 查询

1
2
3
SELECT * 
FROM employees
NATURAL JOIN departments;

结果

emp_id name department_id department_name
1 Alice 10 HR
2 Bob 20 IT
3 Charlie 10 HR
  • NATURAL JOIN 自动使用 department_id 列进行连接。
  • 结果中不再重复显示 department_id 列,因为它已经被自动连接并去除。

总结归纳

SQL 提供了多种 JOIN 操作方式,每种方式根据不同的需求连接表格数据。通过我们在 学生表(Students)成绩表(Scores) 的例子,你可以清晰地了解每种 JOIN 类型的特点和用法。

  • INNER JOIN:返回匹配的记录。
  • LEFT JOIN:返回左表中的所有记录,右表没有匹配的返回 NULL
  • RIGHT JOIN:返回右表中的所有记录,左表没有匹配的返回 NULL
  • FULL JOIN:返回左表和右表中的所有记录,缺少匹配的返回 NULL
  • CROSS JOIN:返回左表和右表的笛卡尔积,所有可能的组合。
  • SELF JOIN:一个表与自身进行连接,通常用于查找表中记录之间的关系。
  • NATURAL JOIN:根据列名相同的列自动连接表。