SELECT e.id, e.name, e.dept, d.manager
FROM doc_test.employees e
INNER JOIN doc_test.departments d
ON e.dept = d.dept_name
ORDER BY e.id;
执行结果(仅显示两表均有匹配的员工):
+----+-------+-------------+---------+
| id | name | dept | manager |
+----+-------+-------------+---------+
| 1 | Alice | Engineering | Charlie |
| 2 | Bob | Engineering | Charlie |
| 3 | Carol | Marketing | Diana |
| 4 | Dave | Marketing | Diana |
| 5 | Eve | HR | Frank |
+----+-------+-------------+---------+
LEFT [OUTER] JOIN
返回
employees
employees
的所有行,
departments
departments
中无匹配时用 NULL 填充。
SELECT e.id, e.name, e.dept, d.dept_id, d.manager
FROM doc_test.employees e
LEFT JOIN doc_test.departments d
ON e.dept = d.dept_name
ORDER BY e.id;
执行结果(所有员工都保留,若
dept
dept
在
departments
departments
中无对应记录则
dept_id
dept_id
/
manager
manager
为 NULL):
+----+-------+-------------+---------+---------+
| id | name | dept | dept_id | manager |
+----+-------+-------------+---------+---------+
| 1 | Alice | Engineering | 1 | Charlie |
| 2 | Bob | Engineering | 1 | Charlie |
| 3 | Carol | Marketing | 2 | Diana |
| 4 | Dave | Marketing | 2 | Diana |
| 5 | Eve | HR | 3 | Frank |
+----+-------+-------------+---------+---------+
RIGHT [OUTER] JOIN
返回
departments
departments
的所有行,
employees
employees
中无匹配时用 NULL 填充。
SELECT e.id, e.name, d.dept_name, d.manager
FROM doc_test.employees e
RIGHT JOIN doc_test.departments d
ON e.dept = d.dept_name
ORDER BY d.dept_id, e.id;
执行结果(所有部门都保留;若某部门无员工,则
id
id
/
name
name
为 NULL):
+------+-------+-------------+---------+
| id | name | dept_name | manager |
+------+-------+-------------+---------+
| 1 | Alice | Engineering | Charlie |
| 2 | Bob | Engineering | Charlie |
| 3 | Carol | Marketing | Diana |
| 4 | Dave | Marketing | Diana |
| 5 | Eve | HR | Frank |
| NULL | NULL | Finance | Grace |
+------+-------+-------------+---------+
FULL [OUTER] JOIN
返回两表所有行,无匹配的一侧用 NULL 填充。
SELECT e.id, e.name, e.dept, d.dept_name, d.manager
FROM doc_test.employees e
FULL JOIN doc_test.departments d
ON e.dept = d.dept_name
ORDER BY e.id, d.dept_id;
执行结果(员工侧和部门侧都完整保留,互相无匹配时对应列为 NULL):
+------+-------+-------------+-------------+---------+
| id | name | dept | dept_name | manager |
+------+-------+-------------+-------------+---------+
| 1 | Alice | Engineering | Engineering | Charlie |
| 2 | Bob | Engineering | Engineering | Charlie |
| 3 | Carol | Marketing | Marketing | Diana |
| 4 | Dave | Marketing | Marketing | Diana |
| 5 | Eve | HR | HR | Frank |
| NULL | NULL | NULL | Finance | Grace |
+------+-------+-------------+-------------+---------+
[LEFT] SEMI JOIN
返回左表中在右表有匹配的行,不返回右表的列。
SELECT e.id, e.name, e.dept
FROM doc_test.employees e
SEMI JOIN doc_test.departments d
ON e.dept = d.dept_name
ORDER BY e.id;
执行结果(只返回员工信息,不含部门表的列):
+----+-------+-------------+
| id | name | dept |
+----+-------+-------------+
| 1 | Alice | Engineering |
| 2 | Bob | Engineering |
| 3 | Carol | Marketing |
| 4 | Dave | Marketing |
| 5 | Eve | HR |
+----+-------+-------------+
[LEFT] ANTI JOIN
返回左表中在右表没有匹配的行,不返回右表的列。
SELECT e.id, e.name, e.dept
FROM doc_test.employees e
ANTI JOIN doc_test.departments d
ON e.dept = d.dept_name
ORDER BY e.id;
执行结果(无
dept
dept
不存在于
departments
departments
的员工时,结果为空):
+----+------+------+
| id | name | dept |
+----+------+------+
(0 rows)
若
employees
employees
中存在部门不在
departments
departments
中的员工,该员工会出现在结果中。
CROSS JOIN
返回两表的笛卡尔积,每行两两组合,结果行数 = 左表行数 × 右表行数。
SELECT e.name, d.dept_name
FROM doc_test.employees e
CROSS JOIN doc_test.departments d
ORDER BY e.id, d.dept_id
LIMIT 9;
执行结果(5 名员工 × 3 个部门 = 15 行,此处截取前 9 行):
+-------+-------------+
| name | dept_name |
+-------+-------------+
| Alice | Engineering |
| Alice | Marketing |
| Alice | HR |
| Bob | Engineering |
| Bob | Marketing |
| Bob | HR |
| Carol | Engineering |
| Carol | Marketing |
| Carol | HR |
+-------+-------------+
NATURAL JOIN
根据两表中所有同名列做隐式等值连接,无需指定 ON 或 USING 条件。
-- NATURAL JOIN:自动按同名列连接
SELECT *
FROM doc_test.employees e
NATURAL JOIN doc_test.departments d;
-- 假设两表都有 dept_name 列,使用 USING 简化
SELECT e.name, e.salary, dept_name, d.manager
FROM doc_test.employees e
JOIN doc_test.departments d
USING (dept_name);
注意事项
JOIN 条件(
ON
ON
子句)不支持子查询。
SEMI JOIN 和 ANTI JOIN 只返回左表的列,即使 SELECT 中引用右表列也会报错。