右外连接在做什么
RIGHT JOIN 是外连接的一种:以右表为基准,右表的每一行都出现在结果里,左表找不到匹配时,左表的列补 NULL。它和把两张表交换位置之后的 LEFT JOIN 完全等价,只是书写顺序不同。实际项目里之所以很少用 RIGHT JOIN,是因为人读 SQL 是按书写顺序从左往右看的,多张表混在一起时很容易判断错哪一侧是保留侧。把连接统一成 LEFT JOIN 链条,能显著降低改错概率。
基本信息
| 适用平台 | MySQL 8.0 / PostgreSQL 12 及以上,标准 SQL 通用 |
|---|---|
| 保留侧 | 右表的全部行都会出现在结果集里 |
| 未匹配处理 | 左表对应列补 NULL,行数不少于右表行数 |
| 等价改写 | 交换两张表的书写顺序后改用左连接,语义完全一致 |
| 团队惯例 | 多表连接统一用左连接链条,减少判断保留侧的心智负担 |
典型使用场景
- 维护历史遗留 SQL:老代码里已经写成右连接,需要读懂保留侧再决定是否改写
- 以业务单据表为基准补全客户主数据,单据表写在右侧
- 补全维表:以维度表为基准,统计哪些维度还没有被业务数据引用
- 双表对齐核对:找出只存在于某一张表里的数据
- 代码评审时逐层确认每张表是保留侧还是被保留侧
示例与等价改写
示例与等价改写
-- 原始写法:保留 users 全部行,左表 orders 缺失时补空
SELECT u.id, u.name, o.id AS order_id
FROM orders o
RIGHT JOIN users u ON u.id = o.user_id;
-- 等价写法:交换两表顺序改用左连接,可读性更好
SELECT u.id, u.name, o.id AS order_id
FROM users u
LEFT JOIN orders o ON o.user_id = u.id;
-- 更常见的目的:找出还没有下过单的用户
SELECT u.id, u.name
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE o.id IS NULL; -- 这一条就是「从未匹配成功」的意思连接类型对照
| 连接写法 | 保留哪一侧 | 未匹配时怎么补 |
|---|---|---|
| INNER JOIN | 只保留两侧都匹配上的行 | 不补,直接丢弃 |
| LEFT JOIN | 保留左表全部行 | 右表列补 NULL |
| RIGHT JOIN | 保留右表全部行 | 左表列补 NULL |
| FULL OUTER JOIN | 两侧都保留 | 各自缺失的一侧补 NULL |
改写时容易忽略过滤条件的位置:放在 ON 里的条件参与匹配判断,放在 WHERE 里的条件作用在结果集上。把针对被保留侧的条件从 ON 挪到 WHERE,会把外连接悄悄退化成内连接。
判断「某张表里没有匹配数据」的通用手法是外连接后对另一侧的主键列做 IS NULL 判断,这个套路在左右连接上都能用,注意判断的列必须是真正会补空的列。