Left join的on后条件不起作用的原因

本文详细解释了SQL中left join的原理与应用,强调on条件与where条件在左连接中的不同作用,帮助读者理解如何正确使用左连接来获取所需数据。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

结论:
left join 为保证左表所有行 因此 on里的条件只对右表起作用,控制左表的条件写到这里也没用
原理:
1、 on条件是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左边表中的记录。
2、where条件是在临时表生成好后,再对临时表进行过滤的条件。这时已经没有left join的含义(必须返回左边表的记录)了,条件不为真的就全部过滤掉。

下面的内容为转载

前天写SQL时本想通过 A left B join on and 后面的条件来使查出的两条记录变成一条,奈何发现还是有两条。

后来发现 join on and 不会过滤结果记录条数,只会根据and后的条件是否显示 B表的记录,A表的记录一定会显示。

不管and 后面的是A.id=1还是B.id=1,都显示出A表中所有的记录,并关联显示B中对应A表中id为1的记录或者B表中id为1的记录。

运行sql : select * from student s left join class c on s.classId=c.id order by s.id

运行sql : select * from student s left join class c on s.classId=c.id and s.name="张三" order by s.id

运行sql :select * from student s left join class c on s.classId=c.id and c.name="三年级三班" order by s.id

数据库在通过连接两张或多张表来返回记录时,都会生成一张中间的临时表,然后再将这张临时表返回给用户。
在使用left jion时,on和where条件的区别如下:

1、 on条件是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左边表中的记录。

2、where条件是在临时表生成好后,再对临时表进行过滤的条件。这时已经没有left join的含义(必须返回左边表的记录)了,条件不为真的就全部过滤掉。
假设有两张表:

表1:tab2

idsize
110
220
330

表2:tab2

sizename
10AAA
20BBB
20CCC

两条SQL:

1、select * form tab1 left join tab2 on (tab1.size = tab2.size) where tab2.name=’AAA’
2、select * form tab1 left join tab2 on (tab1.size = tab2.size and tab2.name=’AAA’)

在这里插入图片描述

在这里插入图片描述
其实以上结果的关键原因就是left join,right join,full join的特殊性,不管on上的条件是否为真都会返回left或right表中的记录,full则具有left和right的特性的并集。 而inner jion没这个特殊性,则条件放在on中和where中,返回的结果集是相同的。

### SQL Left Join 连接条件不匹配时无法正确显示左表所有记录的原因分析 在SQL查询中,`LEFT JOIN` 的行为应当是在右表不存在匹配记录的情况下仍然保留左表的所有记录,并将右表对应的列填充为 `NULL`。然而,有时可能会遇到即使指定了 `LEFT JOIN` ,但在某些情况下表现得像 `INNER JOIN` 一样只返回有匹配的结果。 这种情况通常是由以下几个原因造成的: - **额外的过滤条件放置不当**:如果在 `WHERE` 子句中加入了针对右表字段的非空约束或其他严格条件,则会无意间把那些原本应该被保留下来的左表独占行给排除掉[^1]。 例如,在给出的例子中: ```sql SELECT * FROM quality_process_inspection qpi LEFT JOIN another_table at ON qpi.some_column = at.matching_column WHERE at.another_field IS NOT NULL; ``` 上述查询实际上会在最后一步筛选阶段丢弃任何来自 `quality_process_inspection` 表但是未能找到对应关系的数据行,因为此时 `at.another_field` 将会被设为 `NULL` 而不符合 `IS NOT NULL` 条件。 为了修正这个问题,可以考虑调整逻辑到 `JOIN ... ON` 部分而不是放在 `WHERE` 中处理;或者更谨慎地设计整个查询语句来确保预期的行为得以保持。 ### 正确展示左表所有记录的方法 要确保无论是否存在关联都能看到左边表格里的全部条目,可采取下面几种方法之一: #### 方法一:移除不必要的 WHERE 条件或将它们移到 ON 后面 对于原始问题描述中的情况,可以通过修改查询如下所示来进行修复: ```sql -- 假定 'another_table' 是右边参与 LEFT JOIN 的表名 SELECT * FROM quality_process_inspection qpi LEFT JOIN another_table at ON qpi.some_column = at.matching_column AND at.is_deleted = 0 -- 把 is_deleted=0 放入 ON 子句里 ``` 这样做的好处是可以让所有的 `quality_process_inspection` 记录都得到展现,而不会由于后续的 `WHERE` 约束而导致丢失数据。 #### 方法二:使用 CASE WHEN 或 COALESCE 函数控制输出 另一种解决方案涉及利用函数如 `CASE WHEN` 或者 `COALESCE()` 对特定场景下的值进行特殊处理,从而不影响整体结果集大小的同时达到所需效果。比如: ```sql SELECT qpi.*, CASE WHEN at.id IS NULL THEN 'No Match Found' ELSE CONCAT('Matched with ID:', CAST(at.id AS CHAR)) END as match_info FROM quality_process_inspection qpi LEFT JOIN another_table at ON qpi.some_column = at.matching_column; ``` 这种方法不仅能够维持完整的左表记录列表,还可以提供关于是否有成功配对的信息反馈。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值