找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

5916

积分

0

好友

758

主题
发表于 3 天前 | 查看: 6| 回复: 0

前两天写 SQL 时,本想通过 A LEFT JOIN B ON 后面的条件把查出的两条记录筛成一条,结果发现还是返回了两条。

后来才搞明白:LEFT JOINON 条件不会过滤结果记录条数,它只会根据 AND 后面的条件决定是否显示右表(B 表)的记录,左表(A 表)的记录一定会显示出来。

不管 AND 后面写的是 A.id = 1 还是 B.id = 1,都会把 A 表中所有记录都查出来,同时按条件关联显示 B 表中对应的行。下面用学生表关联班级表来验证一下。

运行 SQL:

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

LEFT JOIN 基础查询结果:学生表关联班级表

运行 SQL:

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

LEFT JOIN 加 AND 条件限定左表 student 的查询结果

运行 SQL:

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

LEFT JOIN 加 AND 条件限定右表 class 的查询结果

数据库在通过连接两张或多张表返回记录时,都会先生成一张中间临时表,再把这张临时表返回给用户。

在使用 LEFT JOIN 时,ON 条件和 WHERE 条件的区别如下:

  1. ON 条件是在生成临时表时使用的条件。它不管 ON 中的条件是否为真,都会返回左边表中的记录。
  2. WHERE 条件是在临时表生成好之后,再对临时表进行过滤的条件。此时已经没有 LEFT JOIN 必须返回左表记录的含义了,条件不为真的行会被全部过滤掉。

假设有两张表:

表1:tab1

id size
1 10
2 20
3 30

表2:tab2

size name
10 AAA
20 BBB
30 CCC

两条 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’)

第一条 SQL 的执行过程:

1、先按 ON 条件生成中间表:

tab1.size = tab2.size

LEFT JOIN ON 条件生成中间表的查询结果

2、再对中间表过滤 WHERE 条件:

tab2.name=’AAA’

中间表经 WHERE 过滤后的最终查询结果

第二条 SQL 的执行过程:

1、中间表 ON 条件:

tab1.size = tab2.size and tab2.name=’AAA’

条件不为真时,也会返回左表中的记录:

LEFT JOIN ON 且 AND tab2.name='AAA' 的中间表结果

其实上面这些结果差异的关键原因,就在于 LEFT JOINRIGHT JOINFULL JOIN 的特殊性:不管 ON 上的条件是否为真,都会返回左表或右表中的记录,FULL JOIN 则兼具左表和右表的特性,取两者并集。而 INNER JOIN 没有这个特殊性,条件放在 ON 中还是 WHERE 中,返回的结果集是相同的。

这类 JOIN 条件差异的坑,在日常业务 SQL 里并不少见。更多 MySQL 实战经验,欢迎来云栈社区一起交流。




上一篇:Windows 远程别再只用 mstsc,1Remote 开源多协议会话管理实操指南
下一篇:阿里三连问:3个if-else也上策略模式?过度设计还是类爆炸?
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-8-26 01:44 , Processed in 1.075113 second(s), 42 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表