> 技术文档 > SQL JOIN 全解析:用 `users` 与 `orders` 表彻底掌握内连接、左连接、右连接

SQL JOIN 全解析:用 `users` 与 `orders` 表彻底掌握内连接、左连接、右连接


SQL JOIN 全解析:用 usersorders 表彻底掌握内连接、左连接、右连接

在日常开发中,SQL 的连接(JOIN)语句是数据库查询的核心技能。尤其在多表联合查询时,不掌握好 INNER JOINLEFT JOINRIGHT JOIN,你就很容易写出“行数膨胀”、数据丢失、NULL 满天飞的奇怪结果。

本文将用两张简单的表 users用户)和 orders订单)作为例子,深入讲解三种常见的连接方式。


一、准备工作:建表与数据

我们先创建两张表并插入一些测试数据。

表结构:

-- 用户表:左表CREATE TABLE users ( id INT PRIMARY KEY, name VARCHAR(50));-- 订单表:右表CREATE TABLE orders ( id INT PRIMARY KEY, user_id INT, item VARCHAR(100), FOREIGN KEY (user_id) REFERENCES users(id));

示例数据:

-- 插入用户数据INSERT INTO users (id, name) VALUES(1, \'孙悟空\'),(2, \'苏有朋\'),(3, \'李白\'),(4, \'赵云\'),(5, \'诸葛亮\');-- 插入订单数据INSERT INTO orders (id, user_id, item) VALUES(101, 1, \'金箍棒\'),(102, 2, \'琵琶\'),(103, 1, \'筋斗云\'),(104, 99, \'无主之剑\'); -- 注意:user_id=99 不存在于 users 中

二、INNER JOIN:内连接

SELECT a.id, a.name, b.itemFROM users aINNER JOIN orders b ON a.id = b.user_id;

结果:

id name item 1 孙悟空 金箍棒 2 苏有朋 琵琶 1 孙悟空 筋斗云

特点:

  • 只保留能成功匹配的记录。
  • user_id=99 的订单匹配不到 → 被排除。
  • 李白赵云诸葛亮没下单 → 被排除。
  • 孙悟空有两个订单 → 出现两次。

总结一句话:

内连接 = 两边都有才要。


三、LEFT JOIN:左连接

SELECT a.id, a.name, b.itemFROM users aLEFT JOIN orders b ON a.id = b.user_id;

结果:

id name item 1 孙悟空 金箍棒 1 孙悟空 筋斗云 2 苏有朋 琵琶 3 李白 NULL 4 赵云 NULL 5 诸葛亮 NULL

特点:

  • 保留所有左表(users)数据
  • 匹配不到的订单信息 → 填充为 NULL
  • user_id=99 的订单仍然被丢弃。

总结一句话:

左连接 = 左边全保,右边能连就连,不能连就补 NULL。


四、RIGHT JOIN:右连接

SELECT a.id, a.name, b.itemFROM users aRIGHT JOIN orders b ON a.id = b.user_id;

结果:

id name item 1 孙悟空 金箍棒 1 孙悟空 筋斗云 2 苏有朋 琵琶 NULL NULL 无主之剑

特点:

  • 保留所有右表(orders)数据
  • 匹配不到的用户信息 → 补 NULL
  • user_id=99 没用户匹配 → 仍然出现在结果中。

总结一句话:

右连接 = 右边全保,左边对不上就补 NULL。


五、膨胀现象:JOIN 会让行数增加吗?

是的!比如:

SELECT a.*, b.*FROM users aLEFT JOIN orders b ON a.id = b.user_id;

你可能以为每个用户只出现一行,结果 孙悟空 出现了两次。

原因:

  • JOIN 会对满足条件的所有组合都生成结果。
  • 孙悟空有两个订单 → 出现两行。
  • 赵云没下单 → 也会保留一行(item=NULL)。

小贴士:

连接时不是“找一个就停”,而是“所有匹配的都拿出来”。


六、常见场景推荐

场景 推荐 JOIN 只看有订单的用户 INNER JOIN 列出所有用户 + 他们的订单情况 LEFT JOIN 列出所有订单 + 是否找到下单用户 RIGHT JOIN 查出哪些用户没有下单 LEFT JOIN + WHERE b.id IS NULL

示例:

SELECT a.id, a.nameFROM users aLEFT JOIN orders b ON a.id = b.user_idWHERE b.id IS NULL;

结语

  • JOIN 本质上是“表之间的行配对”,不只是挑字段而已。
  • 行数会膨胀,尤其是一对多、多对多连接时尤为明显。
  • 熟练掌握 JOIN,才能写出既高效又准确的 SQL 查询。

一图了解JOIN

在这里插入图片描述

参考链接

  • SQL Joins Visualizer
    一目了然地展示各种 JOIN 类型行为。

  • LeetCode SQL Tutorial(JOIN 练习)
    通过实战题目巩固 JOIN 和子查询等知识点。

  • W3Schools:SQL JOIN
    基础入门首选,配有图解和在线练习。

  • MySQL JOIN 语法官方文档
    官方介绍各种 JOIN 的语法规则和性能提示。

  • PostgreSQL JOIN Types
    PostgreSQL 对 JOIN 的详细描述,适用于所有标准 SQL 数据库。

  • Join Data In SQL

在这里插入图片描述