MySQL 的各种关联查询(JOIN)
1. 准备示例数据
我们先创建两张表:employees(员工表) 和 departments(部门表)
CREATE TABLE departments (dept_id INT PRIMARY KEY,dept_name VARCHAR(50)
);CREATE TABLE employees (emp_id INT PRIMARY KEY,emp_name VARCHAR(50),dept_id INT
);INSERT INTO departments VALUES
(1, '研发部'),
(2, '市场部'),
(3, '人事部');INSERT INTO employees VALUES
(101, '张三', 1),
(102, '李四', 1),
(103, '王五', 2),
(104, '赵六', NULL);
2. 各种关联查询类型
2.1 INNER JOIN(内连接)
作用:只返回两个表中匹配的记录。
SELECT e.emp_id, e.emp_name, d.dept_name
FROM employees e
INNER JOIN departments d
ON e.dept_id = d.dept_id;
结果:
| emp_id | emp_name | dept_name |
|---|---|---|
| 101 | 张三 | 研发部 |
| 102 | 李四 | 研发部 |
| 103 | 王五 | 市场部 |
2.2 LEFT JOIN(左连接)
作用:返回左表的所有记录,即使右表没有匹配,也会显示(右表字段为 NULL)。
SELECT e.emp_id, e.emp_name, d.dept_name
FROM employees e
LEFT JOIN departments d
ON e.dept_id = d.dept_id;
结果:
| emp_id | emp_name | dept_name |
|---|---|---|
| 101 | 张三 | 研发部 |
| 102 | 李四 | 研发部 |
| 103 | 王五 | 市场部 |
| 104 | 赵六 | NULL |
2.3 RIGHT JOIN(右连接)
作用:返回右表的所有记录,即使左表没有匹配,也会显示(左表字段为 NULL)。
SELECT e.emp_id, e.emp_name, d.dept_name
FROM employees e
RIGHT JOIN departments d
ON e.dept_id = d.dept_id;
结果:
| emp_id | emp_name | dept_name |
|---|---|---|
| 101 | 张三 | 研发部 |
| 102 | 李四 | 研发部 |
| 103 | 王五 | 市场部 |
| NULL | NULL | 人事部 |
2.4 FULL JOIN(全连接)
作用:返回左右表的所有记录(MySQL 不直接支持 FULL JOIN,需要用 UNION 模拟)。
SELECT e.emp_id, e.emp_name, d.dept_name
FROM employees e
LEFT JOIN departments d
ON e.dept_id = d.dept_id
UNION
SELECT e.emp_id, e.emp_name, d.dept_name
FROM employees e
RIGHT JOIN departments d
ON e.dept_id = d.dept_id;
结果:
| emp_id | emp_name | dept_name |
|---|---|---|
| 101 | 张三 | 研发部 |
| 102 | 李四 | 研发部 |
| 103 | 王五 | 市场部 |
| 104 | 赵六 | NULL |
| NULL | NULL | 人事部 |
2.5 CROSS JOIN(交叉连接 / 笛卡尔积)
作用:返回左右表的所有组合(没有 ON 条件)。
SELECT e.emp_name, d.dept_name
FROM employees e
CROSS JOIN departments d;
结果:每个员工和每个部门都会组合一次(4×3=12 行)。
2.6 SELF JOIN(自连接)
作用:同一张表自己关联自己,常用于层级结构查询。
假设我们有一个 manager_id 字段表示上级:
ALTER TABLE employees ADD manager_id INT;UPDATE employees SET manager_id = NULL WHERE emp_id = 101;
UPDATE employees SET manager_id = 101 WHERE emp_id IN (102, 103, 104);SELECT e.emp_name AS 员工, m.emp_name AS 上级
FROM employees e
LEFT JOIN employees m
ON e.manager_id = m.emp_id;
结果:
| 员工 | 上级 |
|---|---|
| 张三 | NULL |
| 李四 | 张三 |
| 王五 | 张三 |
| 赵六 | 张三 |
3. 总结对比表
| 类型 | 作用 | 是否显示不匹配记录 |
|---|---|---|
| INNER JOIN | 只显示匹配记录 | 否 |
| LEFT JOIN | 显示左表全部记录 | 是(右表为 NULL) |
| RIGHT JOIN | 显示右表全部记录 | 是(左表为 NULL) |
| FULL JOIN | 显示左右表全部记录 | 是 |
| CROSS JOIN | 笛卡尔积 | 全部组合 |
| SELF JOIN | 自己关联自己 | 取决于条件 |
