inner join只返回两表匹配的行,left join保留左表所有行且右表无匹配时补null;选择依据是是否需要保留左表缺失关联数据的记录。

INNER JOIN 和 LEFT JOIN 选哪个,取决于你要不要“缺失数据”
如果业务要求必须有对应记录才能返回(比如查已支付订单的用户信息),用 INNER JOIN;如果要保留主表全部数据,哪怕关联表没匹配项(比如查所有客户,含未下单者),必须用 LEFT JOIN。
常见错误是把过滤条件写错位置:对 LEFT JOIN 的右表加 WHERE 条件,会把本该为 NULL 的行直接过滤掉,实际效果等同于 INNER JOIN。
- 错误写法:
LEFT JOIN orders o ON u.id = o.user_id WHERE o.status = 'paid'→ 无订单用户消失 - 正确写法:
LEFT JOIN orders o ON u.id = o.user_id AND o.status = 'paid'→ 保留所有用户,无匹配则o.*全为NULL - 多条件
ON可用AND连接,例如:ON a.id = b.a_id AND b.deleted = 0
三张及以上表连接,顺序和别名不能乱
MySQL 优化器通常能重排执行顺序,但人写的 SQL 要逻辑清晰。推荐以主表(如 users)开头,逐级关联从表(orders → order_items → products),每层 JOIN 后紧跟对应的 ON 条件。
字段重名(比如多个表都有 id)必须用别名区分,否则报错或结果错乱。
- 给表起简短别名:
FROM users u INNER JOIN orders o ON u.id = o.user_id -
ON必须紧贴对应JOIN,不能堆在最后统一写 - 避免
SELECT *,只取需要字段,减少传输和内存压力
慢查询?先看索引有没有建在 ON 字段上
JOIN 性能瓶颈八成出在缺少索引。被驱动表(ON 右边的表)的关联字段必须有索引,否则可能触发全表扫描。
例如:orders.user_id、order_items.order_id、products.category_id 都应建索引。复合索引要注意最左前缀原则,比如 INDEX(user_id, status) 能加速 ON u.id = o.user_id AND o.status = 'paid'。
- 用
EXPLAIN看执行计划,重点观察type是否为ref或eq_ref,key是否命中索引 - 如果
type是ALL,基本确认没走索引 - 连接字段类型要严格一致(比如
INT对INT,别用VARCHAR存数字 ID)
MySQL 不支持 FULL OUTER JOIN,但可以模拟
真要取两表全部记录(不管是否匹配),MySQL 没原生 FULL OUTER JOIN,得靠 LEFT JOIN + RIGHT JOIN + UNION ALL 组合实现:
SELECT u.*, o.* FROM users u LEFT JOIN orders o ON u.id = o.user_id UNION ALL SELECT u.*, o.* FROM users u RIGHT JOIN orders o ON u.id = o.user_id WHERE u.id IS NULL;
这种写法性能差、可读性低,生产环境尽量避免。多数场景其实只需要 LEFT JOIN 或拆成两次查询更可控。
真正容易被忽略的是:JOIN 的本质是笛卡尔积 + 过滤,表越大、条件越松,中间结果集爆炸得越快——不是语法写对了就行,得时刻盯着数据量和索引有效性。











