SQL Join语句中应用on与where的区别

举报
gentle_zhou 发表于 2023/12/16 20:21:35 2023/12/16
【摘要】 如果只是内连接(INNER JOIN)类型的语句,那么ON和WHERE的效果是一样的。 如果是外连接(LEFT JOIN,RIGHT JOIN,FULL JOIN)类型的语句,那么ON和WHERE的效果是不一样的

在上一篇文章《数据库SQL语法多种Join类型介绍》中,我们介绍了4种类型的JOIN语句:Inner Join、Left Join、Right Join、Full Join。它们的目的都是基于两个或多个表之间的共同字段,把这些表中的字段通过某种方式结合起来。

我们先抛出一个带有Inner Join语法 以及 ON关系的SQL语句:

SELECT * 
FROM table1 
INNER JOIN table2 
ON table1.column = table2.column;

在这个语法中,ON后面关联着两张表之间的关联条件,是一个或多个逻辑表达式,用来判断两个表中的记录是否相等或满足其他条件。上面这条语句中,会返回两个表中满足ON条件的所有记录,即table1.column和table2.column的值相等的记录。

除了ON之外,我们还可以通过WHERE来关联两张或多个表之间。比如上面那个SQL语句,我们也可以用下面含有WHERE的语句来表示:

SELECT * 
FROM table1, table2 
WHERE table1.column = table2.column;

这条语句会返回两个表中满足WHERE条件的所有记录,即table1.column和table2.column的值相等的记录。上述两个语句(ON和WHERE)的效果是一样的,即返回的记录是一致的,因为它们都是内连接(INNER JOIN)类型,会返回两个表中匹配的记录。但这对于所有Join类型都是一致的效果吗?

在对比说明之前,我们需要明确一点:数据库在通过连接两张或多张表来返回结果记录时,都会生成一张临时表,然后再将这张临时表(部分情况下还会处理下)返回给用户。

而ON 和 WHERE 的区别就主要在于连接的类型和过滤的时机上。ON语法是在生成临时表时使用的条件,它会根据两个表中连接字段来匹配记录,不管条件是否为真,都会返回其中一个表中的记录(返回哪个表取决于连接的类型,left join, right join等)。WHERE语法则是在临时表生成后使用的条件,在临时表生成后,再对临时表进行过滤;它会根据指定的条件来筛选记录,和ON语法不同的是,条件不为真的话就会全部过滤掉。综上所述,两者最大的区别就在于,on 是在连接两个表时起作用,而 where 是在连接完成后起作用。

因此,我们需要对所有类型的JOIN语法:Inner Join、Left Join、Right Join、Full Join 进行个分类,在这4种类型语法中,ON 和 WHERE 的效果都是相同的吗?

Inner Join类内连接

如前文中所举的例子,因为内连接会返回两个表中满足条件的记录,不管条件放在哪里,因此对于内连接(Inner Join),ON和WHERE的效果是一样的。

Left Join类外连接

但对于Left Join,Right Join、Full Join这类外连接类型则不一样;它不管ON中的条件是否满足,都只会返回左表(Left Join)或则右表(Right Join)或则两张表(Full Join)的记录。

我们这里买还是拿Left Join举个简单的例子,假设有两张表。一张是id和学生号。

id student_id
1 A1
2 A2
3 B1

另外一张是学生号和学生名字的关联关系。

student_id student_name
A1 小华
A2 小明
B2 小小

WHERE语句

假如我们执行这条SQL语句
SELECT * FROM table1 LEFT JOIN table2 ON table1.student_id = table2.student_id WHERE table2.student_name='小华',我们会得到如下结果:

table1.id table1.student_id table2.student_id table2.student_name
1 A1 A1 小华

因为它会根据两个表中连接字段来匹配记录,不管ON里的条件是否为真,都会返回其中一个表(这里是Left Join,因此就是左表)中的记录。中间表如下:

table1.id table1.student_id table2.student_id table2.student_name
1 A1 A1 小华
2 A2 A2 小明
3 B1 (null) (null)

接着再对中间表过滤where 条件:table2.student_name=‘小华’,就得到最开始的那张表了。

ON语句

接着,我们执行这条语句:SELECT * FROM table1 LEFT JOIN table2 ON table1.student_id = table2.student_id AND table2.student_name='小华',那么此时就只会考虑在生成中间表时ON后面条件过滤(table1.student_id = table2.student_id AND table2.student_name=‘小华’)的影响了,此时中间表会变为:

table1.id table1.student_id table2.student_id table2.student_name
1 A1 A1 小华
2 A2 (null) (null)
3 B1 (null) (null)

而这也是最终输出的记录。

综上所述,对于对于Left Join,Right Join、Full Join这类外连接类型,因为会返回左表 或 右表 或两张表中的所有记录,即使没有匹配的记录;因此在中间表生成期间过滤条件 还是 中间表生成之后过滤条件就变得不一样了,这也导致ON和WHERE的效果不一样了。

总结

  • 如果只是内连接(INNER JOIN)类型的语句,那么ON和WHERE的效果是一样的。因为不管条件放在哪里,内连接只返回两个表中满足条件的记录。
  • 如果是外连接(LEFT JOIN,RIGHT JOIN,FULL JOIN)类型的语句,那么ON和WHERE的效果是不一样的。因为外连接会左表 或 右表 或两张表中的所有记录,即使没有匹配的记录;加上,ON是在生成临时表时使用的条件,而WHERE是在临时表生成好后再使用的条件;那么在中间表生成期间过滤条件 还是 中间表生成之后过滤条件就变得不一样了。
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。