MySQL: MySQL连接查询JOIN完全指南
最后更新:2026-08-26
JOIN 是关系型数据库的核心能力——关联多张表才能发挥真正的威力。
本课系统讲解所有 JOIN 类型及实战应用。
1. 你将学到
- INNER JOIN 内连接
- LEFT JOIN / RIGHT JOIN 外连接
- CROSS JOIN 交叉连接
- 自连接
- USING 语法
2. 多表查询的真实故事
(1) 痛点:数据分散在多张表
订单数据在 orders 表,客户名在 customers 表。
想查"每个订单对应的客户名"——需要关联查询。
(2) JOIN 的解法
SQL
SELECT
o.id AS order_id,
c.name AS customer_name,
o.amount
FROM orders o
INNER JOIN customers c ON o.customer_id = c.id;
3. JOIN 类型总览
graph LR
A[JOIN 类型] --> B[INNER JOIN]
A --> C[LEFT JOIN]
A --> D[RIGHT JOIN]
A --> E[CROSS JOIN]
B --> F[只返回匹配行]
C --> G[左表全返+右表匹配]
D --> H[右表全返+左表匹配]
E --> I[笛卡尔积]
| JOIN 类型 | 说明 | 返回行数 |
|---|---|---|
| INNER JOIN | 两表都匹配的行 | 交集 |
| LEFT JOIN | 左表全部 + 右表匹配 | 左表全量 |
| RIGHT JOIN | 右表全部 + 左表匹配 | 右表全量 |
| CROSS JOIN | 笛卡尔积 | m × n |
4. INNER JOIN 内连接
只返回两表都匹配的行。
▶ 示例:基本内连接
SQL
-- 查询订单及客户信息
SELECT
o.id AS order_id,
c.name AS customer_name,
o.amount,
o.order_date
FROM orders o
INNER JOIN customers c ON o.customer_id = c.id;
-- 三表连接
SELECT
o.id,
c.name,
p.product_name,
oi.quantity
FROM orders o
INNER JOIN customers c ON o.customer_id = c.id
INNER JOIN order_items oi ON o.id = oi.order_id
INNER JOIN products p ON oi.product_id = p.id;
5. LEFT JOIN 左外连接
返回左表所有行,右表无匹配时返回 NULL。
▶ 示例:左连接
SQL
-- 查询所有客户及其订单(包括没订单的客户)
SELECT
c.name,
o.id AS order_id,
o.amount
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id;
输出:
TEXT
📖 仅展示
+----------+----------+--------+
| name | order_id | amount |
+----------+----------+--------+
| Alice | 1 | 100.00 |
| Alice | 2 | 200.00 |
| Bob | 3 | 150.00 |
| Charlie | NULL | NULL | -- 没有订单
+----------+----------+--------+
▶ 示例:找出没有订单的客户
SQL
SELECT c.*
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id
WHERE o.id IS NULL;
6. RIGHT JOIN 右外连接
返回右表所有行,左表无匹配时返回 NULL。
▶ 示例:右连接
SQL
-- 查询所有订单及其客户(包括无效订单)
SELECT
c.name,
o.id AS order_id,
o.amount
FROM customers c
RIGHT JOIN orders o ON c.id = o.customer_id;
💡 提示: RIGHT JOIN 较少使用,通常可以用 LEFT JOIN 替代(调换表顺序)。
7. CROSS JOIN 交叉连接
返回笛卡尔积(每行 × 每行)。
▶ 示例:交叉连接
SQL
-- 生成颜色×尺寸组合
SELECT c.color, s.size
FROM colors c
CROSS JOIN sizes s;
输出(3 色 × 3 尺寸 = 9 行):
TEXT
📖 仅展示
+-------+------+
| color | size |
+-------+------+
| Red | S |
| Red | M |
| Red | L |
| Blue | S |
| Blue | M |
| Blue | L |
| Green | S |
| Green | M |
| Green | L |
+-------+------+
8. USING 语法
当连接字段名相同时,可用 USING 简化。
▶ 示例:USING 简化
SQL
-- ON 写法
SELECT * FROM orders o
INNER JOIN customers c ON o.customer_id = c.id;
-- USING 简化(字段名必须相同)
SELECT * FROM orders
INNER JOIN customers USING (customer_id);
9. 自连接
表与自身关联。
▶ 示例:查找员工及其上级
SQL
-- 员工表有 manager_id 字段指向自己的 id
SELECT
e.name AS employee,
m.name AS manager
FROM employees e
LEFT JOIN employees m ON e.manager_id = m.id;
输出:
TEXT
📖 仅展示
+----------+---------+
| employee | manager |
+----------+---------+
| Alice | NULL | -- CEO,无上级
| Bob | Alice |
| Charlie | Alice |
| Dave | Bob |
+----------+---------+
10. JOIN 优化基础
| 优化策略 | 说明 |
|---|---|
| 连接字段加索引 | ON o.customer_id = c.id 中的字段要有索引 |
| 小表驱动大表 | 小结果集的表放左边 |
避免 SELECT * |
只查需要的字段 |
| WHERE 提前过滤 | 减少参与 JOIN 的行数 |
❓ 常见问题
Q INNER JOIN 和 JOIN 有区别吗?
A 没有。
JOIN 默认就是 INNER JOIN。Q LEFT JOIN 和 RIGHT JOIN 能互换吗?
A 可以。
A LEFT JOIN B 等价于 B RIGHT JOIN A。推荐统一用 LEFT JOIN。Q JOIN 会很慢吗?
A 取决于数据量和索引。连接字段有索引时,百万级表 JOIN 也能秒级返回。
Q 能 JOIN 多少张表?
A MySQL 理论无限制,但实际建议不超过 5-6 张。表太多考虑反范式设计。
📖 小节
- INNER JOIN 返回两表匹配的行
- LEFT JOIN 返回左表全部 + 右表匹配(常用)
- RIGHT JOIN 返回右表全部 + 左表匹配
- CROSS JOIN 返回笛卡尔积
- 自连接 表与自身关联
- USING 简化同名字段的连接
- 连接字段加索引是关键优化手段
📝 作业
-
基础题(难度⭐):用 INNER JOIN 查询订单及对应客户名称。
-
进阶题(难度⭐⭐):用 LEFT JOIN 找出从未下单的客户。
-
挑战题(难度⭐⭐⭐):用自连接查询员工及其上级,统计每个上级管理的下属数量。