深入解析 LEFT JOIN 和 RIGHT JOIN

一、LEFT JOIN(左连接)详解

核心机制

  1. 保留左表所有行:无论右表是否有匹配记录

  2. 匹配右表数据:当匹配成功时,合并左右表数据

  3. NULL 填充:当右表无匹配时,右表字段用 NULL 填充

  4. 一对多关系:左表一行可能对应右表多行

完整语法

SELECT 列列表
FROM 左表
LEFT [OUTER] JOIN 右表 
    ON 连接条件
[WHERE 过滤条件];

执行流程

从左表取第一行

扫描右表所有行,寻找满足 ON 条件的记录

找到匹配:合并行加入结果集

未找到匹配:左表数据 + 右表 NULL 值加入结果集

重复上述过程处理左表所有行

典型应用场景

主从关系查询:

-- 所有产品及其销售记录(包括无销售的产品)
SELECT p.product_id, p.name, s.sale_date, s.quantity
FROM products p
LEFT JOIN sales s ON p.product_id = s.product_id;

查找缺失数据:

-- 从未被订购的产品
SELECT p.product_id, p.name
FROM products p
LEFT JOIN orders o ON p.product_id = o.product_id
WHERE o.order_id IS NULL;

层级结构展示:

-- 所有部门及其员工(包括空部门)
SELECT d.department_name, e.employee_name
FROM departments d
LEFT JOIN employees e ON d.department_id = e.department_id;

注意事项

ON vs WHERE:

ON 条件决定如何连接

WHERE 条件在连接后过滤结果

-- 错误:会过滤掉没有订单的客户
SELECT c.name, o.order_date
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id
WHERE o.order_date > '2023-01-01';
--WHERE子句在LEFT JOIN后执行,会强制将不满足条件的右表记录(包括NULL记录)过滤掉
--导致没有2023年后订单的客户会被排除,LEFT JOIN退化为INNER JOIN
--最终结果丢失了没有订单的客户记录,
--简述,如果放在where里面,就是在新生成表里面过滤,


-- 正确:将日期条件放在ON中
SELECT c.name, o.order_date
FROM customers c
LEFT JOIN orders o ON c.id = o.customer_id 
   AND o.order_date > '2023-01-01';
--过滤条件作为连接条件的一部分,在JOIN过程中应用
--保留所有客户记录,仅过滤关联的订单记录
--没有匹配订单的客户会显示为NULL,但客户信息仍然保留
--简述,如果放在on里面,就是在 left后面的旧的orders表里面进行筛选,不会影响到另外一个表


多表连接顺序:

SELECT *
FROM A
LEFT JOIN B ON A.id = B.a_id
LEFT JOIN C ON B.id = C.b_id;

性能优化:

在连接列上建立索引

避免在 ON 条件中使用函数

限制 SELECT 的列数

二、RIGHT JOIN(右连接)详解

核心机制

  • 保留右表所有行:无论左表是否有匹配记录

  • 匹配左表数据:当匹配成功时,合并左右表数据

  • NULL 填充:当左表无匹配时,左表字段用 NULL 填充

  • 镜像操作:实质是 LEFT JOIN 的逆向操作

完整语法

SELECT 列列表
FROM 左表
RIGHT [OUTER] JOIN 右表 
 ON 连接条件
[WHERE 过滤条件];

执行流程

从右表取第一行

扫描左表所有行,寻找满足 ON 条件的记录

找到匹配:合并行加入结果集

未找到匹配:右表数据 + 左表 NULL 值加入结果集

重复上述过程处理右表所有行

典型应用场景

逆向主从关系:

-- 所有订单及其客户(强调订单为主体)
SELECT o.order_id, o.amount, c.name
FROM customers c
RIGHT JOIN orders o ON c.id = o.customer_id;

查找孤立数据:

-- 系统中未关联客户的订单
SELECT o.order_id, o.order_date
FROM customers c
RIGHT JOIN orders o ON c.id = o.customer_id
WHERE c.id IS NULL;

数据完整性检查:

-- 检查任务分配情况
SELECT t.task_name, e.employee_name
FROM employees e
RIGHT JOIN tasks t ON e.id = t.assigned_to;

三、注意事项

可替代性:

-- 以下两个查询等价
SELECT * 
FROM A 
RIGHT JOIN B ON A.id = B.a_id;

SELECT * 
FROM B 
LEFT JOIN A ON B.a_id = A.id;

使用频率:

实际开发中 RIGHT JOIN 使用率不足 5%

主要因不符合从左到右的思维习惯

复杂查询中可能降低可读性

特殊场景价值:

当右表是查询主体时更直观

某些数据库优化器对特定写法有优化

四、LEFT JOIN 与 RIGHT JOIN 深度对比

特性LEFT JOINRIGHT JOIN
主表FROM 后的第一个表JOIN 后的第二个表
保留行左表所有行右表所有行
未匹配处理右表字段填充 NULL左表字段填充 NULL
使用频率非常高 (约95%场景)较低 (约5%场景)
可读性符合自然阅读顺序需要逆向思维
等价转换A LEFT JOIN B ≡ B RIGHT JOIN AA RIGHT JOIN B ≡ B LEFT JOIN A
典型应用获取主体信息+关联补充数据强调从表信息完整性
NULL 检测WHERE right_table.id IS NULLWHERE left_table.id IS NULL
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值