SQL表连接终于讲明白了:INNER JOIN、LEFT JOIN、RIGHT JOIN 一次学透
SQL表连接终于讲明白了INNER JOIN、LEFT JOIN、RIGHT JOIN 一次学透很多人学 SQL卡得最久的不是 SELECT、WHERE而是表连接JOIN。这篇就不绕弯直接把 SQL 表连接讲到能上手。一、为什么一定要学会表连接真实业务里数据通常不会全塞在一张表里。比如电商系统里用户信息在users表订单信息在orders表。你想查“每个订单是谁下的”“哪些用户没下单”就必须把多张表关联起来查。JOIN 的本质把不同表中有关联的数据按条件拼接起来。二、先记住 JOIN 的核心结构SELECT 列名 FROM 表A JOIN 表B ON 表A.关联字段 表B.关联字段;比如SELECT users.user_name, orders.order_id, orders.amount FROM users INNER JOIN orders ON users.user_id orders.user_id;ON说白了就是两张表到底凭什么配对。这个条件写错后面全白搭。三、INNER JOIN只要两边都能对上INNER JOIN只返回两张表中能够匹配成功的数据。SELECT users.user_name, orders.order_id, orders.amount FROM users INNER JOIN orders ON users.user_id orders.user_id;如果用户表里有小王、小李、小张订单表里只有小王和小李的订单那么结果中不会出现小张。一句人话总结能配上的留下配不上的滚。四、LEFT JOIN左边全保留右边能接上就接LEFT JOIN的逻辑是以左表为主左表的所有记录都保留右表匹配不上就补NULL。SELECT users.user_name, orders.order_id, orders.amount FROM users LEFT JOIN orders ON users.user_id orders.user_id;这时即使小张没有下单也会出现在结果中只不过订单相关字段是NULL。查“没有下单的用户”时这是高频写法SELECT users.user_id, users.user_name FROM users LEFT JOIN orders ON users.user_id orders.user_id WHERE orders.order_id IS NULL;五、RIGHT JOIN能不用就少用RIGHT JOIN和 LEFT JOIN 一样只是把“主表”换到了右边。大多数团队更习惯把主表写在左侧所以开发里通常更推荐统一使用 LEFT JOIN少用 RIGHT JOIN省得自己给自己上强度。六、FULL OUTER JOIN两边都要谁落单都留下FULL OUTER JOIN会保留左右两边全部记录匹配得上就拼起来匹配不上就补 NULL。这个在数据核对、对账时很好用。不过注意MySQL 不直接支持 FULL OUTER JOIN很多时候需要用UNION模拟。所以如果你是 MySQL 初学者先把 INNER JOIN 和 LEFT JOIN 吃透已经够用了。七、记 JOIN不如记这个问题别死背定义直接问自己一句我到底想保留哪张表的全部数据这个问题一问JOIN 类型通常就出来了INNER JOIN只要交集LEFT JOIN左边全保留RIGHT JOIN右边全保留FULL OUTER JOIN两边都保留八、初学者最容易踩的 4 个坑1忘了写 ON 条件SELECT * FROM users JOIN orders;这要么直接报错要么变成笛卡尔积。别查数据查着查着就把数据库现场炸成烟花。2关联字段不唯一结果重复一对多、多对多关系本来就会让结果行数膨胀。写 JOIN 前先搞清楚关系一对一一对多多对多否则你会以为是 SQL 抽风其实是你没想明白。3LEFT JOIN 后又在 WHERE 里把右表卡死SELECT users.user_name, orders.order_id FROM users LEFT JOIN orders ON users.user_id orders.user_id WHERE orders.amount 100;这会把右表为空的记录过滤掉效果更像 INNER JOIN。更稳的写法是把过滤条件写到ON里SELECT users.user_name, orders.order_id FROM users LEFT JOIN orders ON users.user_id orders.user_id AND orders.amount 100;4字段重名不加表前缀如果两张表里都有user_id那你裸写字段名数据库十有八九会回你一句字段不明确。老老实实写全或者直接上表别名SELECT u.user_name, o.order_id, o.amount FROM users u LEFT JOIN orders o ON u.user_id o.user_id;九、建议直接收藏的 4 个实战模板1查订单和对应用户名SELECT u.user_name, o.order_id, o.amount FROM users u INNER JOIN orders o ON u.user_id o.user_id;2查所有用户及其订单没有订单也显示SELECT u.user_name, o.order_id, o.amount FROM users u LEFT JOIN orders o ON u.user_id o.user_id;3查没有下单的用户SELECT u.user_id, u.user_name FROM users u LEFT JOIN orders o ON u.user_id o.user_id WHERE o.order_id IS NULL;4统计每个用户的订单数SELECT u.user_name, COUNT(o.order_id) AS order_count FROM users u LEFT JOIN orders o ON u.user_id o.user_id GROUP BY u.user_name;十、最后总结INNER JOIN只要匹配成功的数据LEFT JOIN左表全保留右表匹配不上就 NULL查“没有”优先想 LEFT JOIN IS NULLLEFT JOIN 右表过滤很多时候要写在 ON 里不要乱塞 WHERESQL 表连接不难它只是经常被讲得很绕。一旦你抓住“保留谁”这个核心JOIN 基本就顺了。