当前位置:首页 > 问答 > 正文

数据库 关系型 图说MySQL多种join连接方式详解

图说MySQL多种JOIN连接方式详解:原来SQL还能这么玩!

场景引入:外卖小哥的烦恼

小王最近兼职送外卖,发现后台系统经常卡顿,技术主管老张排查后发现,有个查询订单和用户信息的SQL写得特别慢——它把两个表的所有数据先查出来,再在代码里手动匹配。

"这不行啊!"老张拍桌道,"该用JOIN的时候不用,数据库白学了!" 于是连夜给小王的团队补了一堂MySQL JOIN课...


JOIN基础:表的"连连看"

想象两张Excel表格:

  • 用户表(id, 姓名, 手机号)
  • 订单表(订单号, 用户id, 金额)

JOIN就是根据"用户id"这个共同字段,把两张表的数据智能拼接,MySQL主要支持这几种玩法:


5种JOIN详解(配图说明)

INNER JOIN:只返回匹配成功的"交集"

SELECT users.姓名, orders.订单号 
FROM users 
INNER JOIN orders ON users.id = orders.用户id;

效果:像严格的门卫,只放行两边表能对应上的记录(没下过单的用户、无人认领的订单都会被过滤)

![INNER JOIN示意图:两个圆圈重叠的阴影部分]

数据库 关系型 图说MySQL多种join连接方式详解


LEFT JOIN:左表是"亲儿子"

SELECT users.姓名, orders.订单号
FROM users 
LEFT JOIN orders ON users.id = orders.用户id;

效果:左表(users)所有记录都会显示,右表找不到匹配就填NULL(适合查"哪些用户从未下单")

![LEFT JOIN示意图:左圆完整显示,右圆只显示重叠部分]


RIGHT JOIN:右表是"亲儿子"

SELECT users.姓名, orders.订单号
FROM users 
RIGHT JOIN orders ON users.id = orders.用户id;

效果:与LEFT JOIN相反,右表(orders)全保留(适合找"无主订单")

注:实际开发中较少使用,通常用LEFT JOIN调换表顺序替代


FULL OUTER JOIN:我全都要(MySQL的替代方案)

MySQL不直接支持,但可以用UNION模拟:

SELECT users.姓名, orders.订单号 FROM users LEFT JOIN orders ON users.id = orders.用户id
UNION
SELECT users.姓名, orders.订单号 FROM users RIGHT JOIN orders ON users.id = orders.用户id;

效果:显示所有用户和所有订单,匹配不上的补NULL

![FULL JOIN示意图:两个圆圈合并显示]

数据库 关系型 图说MySQL多种join连接方式详解


CROSS JOIN:笛卡尔积的狂欢

SELECT users.姓名, orders.订单号
FROM users 
CROSS JOIN orders;

效果:左表每条记录配右表所有记录(用户数×订单数条结果),慎用!


性能优化小贴士

  1. 索引是命根子:JOIN字段务必建索引(如orders.用户id)
  2. 小表驱动大表:把数据量小的表放在JOIN左侧
  3. **别SELECT ***:只查询需要的字段,减少数据传输
  4. EXPLAIN神器:执行前用EXPLAIN查看执行计划

实战选择题

场景:统计每个用户的消费总金额(包含零消费用户)

-- 方案A
SELECT users.姓名, SUM(orders.金额) 
FROM users LEFT JOIN orders ON users.id = orders.用户id
GROUP BY users.id;
-- 方案B
SELECT users.姓名, SUM(orders.金额) 
FROM users INNER JOIN orders ON users.id = orders.用户id
GROUP BY users.id;

答案:方案A(LEFT JOIN能保留零消费用户)


老张最后总结道:"JOIN就像谈恋爱——INNER JOIN是双向奔赴,LEFT JOIN是单相思,CROSS JOIN是乱点鸳鸯谱..." 小王恍然大悟,第二天就把系统查询速度优化了3倍。

下次遇到多表查询时,不妨先想想:这次该用哪种"连接姿势"?

发表评论