
【MySQL 笔记】多表查询Multi-Table Query / JOIN详解多表查询是 MySQL 中最核心、最常用的技能之一几乎所有真实业务场景订单用户、商品分类、员工部门等都离不开它。一、MySQL 多表查询核心方式对比2026 年主流用法查询方式关键字 / 写法保留哪些行结果行数特征性能影响典型业务场景推荐指数隐式连接旧写法FROM A, B WHERE A.id B.id只匹配的行相当于 INNER JOIN≤ min(A,B)中等历史代码、简单查询★★☆☆☆INNER JOININNER JOIN / JOIN两表都匹配的行≤ min(A,B)较好必须双方都有数据的查询★★★★★LEFT [OUTER] JOINLEFT JOIN左表全部 右表匹配右缺→NULL 左表行数中等查所有商品 是否有销量没卖的也显示★★★★★RIGHT [OUTER] JOINRIGHT JOIN右表全部 左表匹配左缺→NULL 右表行数中等查所有课程 报名情况★★★★☆FULL [OUTER] JOINFULL JOINMySQL 不原生支持两表全部不匹配补 NULL≈ A B - 交集较高数据对账、找出差异记录★★★★☆CROSS JOINCROSS JOIN / ,逗号无条件笛卡尔积每行×每行 A行数 × B行数高爆炸生成测试数据、全组合★★☆☆☆SELF JOIN表自己 JOIN 自己用别名同表不同角色匹配取决于 ON 条件中等员工-经理、分类父子、上下级★★★★☆二、经典示例表建议自己建表练习-- 部门表CREATETABLEdept(deptnoINTPRIMARYKEY,dnameVARCHAR(20),locVARCHAR(20));INSERTINTOdeptVALUES(10,RESEARCH,BEIJING),(20,SALES,SHANGHAI),(30,ACCOUNTING,GUANGZHOU),(40,OPERATIONS,SHENZHEN);-- 没人-- 员工表CREATETABLEemp(empnoINTPRIMARYKEY,enameVARCHAR(20),jobVARCHAR(20),mgrINT,-- 领导编号自关联salDECIMAL(10,2),deptnoINT,FOREIGNKEY(deptno)REFERENCESdept(deptno));INSERTINTOempVALUES(7369,SMITH,CLERK,7902,800.00,20),(7499,ALLEN,SALESMAN,7698,1600.00,30),(7521,WARD,SALESMAN,7698,1250.00,30),(7566,JONES,MANAGER,7839,2975.00,20),(7698,BLAKE,MANAGER,7839,2850.00,30),(7782,CLARK,MANAGER,7839,2450.00,10),(7839,KING,PRESIDENT,NULL,5000.00,10);三、各种 JOIN 实战写法全部敲一遍最有感觉-- 1. INNER JOIN最常用SELECTe.ename,e.job,d.dname,d.locFROMemp eINNERJOINdept dONe.deptnod.deptno;-- 结果只显示有部门的员工deptno40 的部门没人不显示-- 2. LEFT JOIN保留左表全部SELECTe.ename,e.job,d.dname,d.locFROMemp eLEFTJOINdept dONe.deptnod.deptno;-- 结果所有员工 部门信息即使 deptno 不匹配也显示员工dname 为 NULL-- 3. RIGHT JOIN保留右表全部SELECTe.ename,d.dname,d.locFROMemp eRIGHTJOINdept dONe.deptnod.deptno;-- 结果所有部门 员工OPERATIONS 部门没人ename 为 NULL-- 4. MySQL 模拟 FULL JOIN最常见写法(SELECTe.ename,d.dnameFROMemp eLEFTJOINdept dONe.deptnod.deptno)UNION(SELECTe.ename,d.dnameFROMemp eRIGHTJOINdept dONe.deptnod.deptnoWHEREe.deptnoISNULL);-- 结果所有员工 所有部门没匹配的补 NULL-- 5. CROSS JOIN笛卡尔积慎用SELECTe.ename,d.dnameFROMemp eCROSSJOINdept d;-- 结果7员工 × 4部门 28 行爆炸-- 6. SELF JOIN员工找上级SELECTe.enameAS员工,m.enameAS上级FROMemp eLEFTJOINemp mONe.mgrm.empno;-- 结果显示每个员工及其直接领导KING 没有上级 → NULL-- 7. 三表联查示例部门 → 员工 → 上级SELECTe.ename,e.job,d.dname,m.enameASmanager_nameFROMemp eINNERJOINdept dONe.deptnod.deptnoLEFTJOINemp mONe.mgrm.empno;四、高频业务场景总结面试 实战场景推荐 JOIN 类型关键写法技巧订单详情 用户信息必须有用户INNER JOIN脏数据过滤所有商品 最近销量没卖出显示0LEFT JOIN COALESCECOALESCE(sales, 0)所有课程 选课人数没人选也显示LEFT JOIN GROUP BYCOUNT(student_id)找出只在一张表有的记录FULL JOIN模拟或 LEFTIS NULLWHERE 右表.id IS NULL员工上下级关系SELF JOIN用别名区分角色生成测试数据组合CROSS JOIN LIMIT控制行数五、写多表查询的实用技巧 2026 年注意点永远写 ON 条件别把连接条件写 WHERE容易逻辑错乱小表驱动大表LEFT JOIN 时把小表放左边优化器通常会调整但显式写好JOIN 字段必须有索引尤其是外键、主键、频繁 ON 的列用表别名e、d、o、u 常用清晰 避免歧义NULL 判断LEFT JOIN 后常用WHERE xx IS NULL找“只有左表有的”EXPLAIN 验证写完复杂 JOIN 后先 EXPLAIN 看执行计划**避免 SELECT ***明确列出需要的字段减少 IO下一期预告建议MySQL 子查询Subquery全家桶 相关子查询 vs 非相关 IN / EXISTS 性能对比有特别迷惑的多表查询写法比如三表以上、复杂过滤、性能卡住等欢迎留言我们一起画图分析祝大家 JOIN 写得又准又快