SQL语句中连接on条件和where条件的执行顺序

缘起

首先,来看下面的SQL查询语句

select 
 *
from a left join b on a.id = b.a_id
where b.name='apple'

我期望的结果是:表a的数据全部展示出来,然后,过滤掉不符合表b条件的结果。
但是,答案却出乎我的意料,所有数据都被过滤掉了,最终结果并不符合left join的语义,表a是主表,无论如何是应该展示出来的,但是并没有。
问题出在哪里呢?

原理分析

这里牵扯到的是sql语句中on后的条件和where后的条件的执行顺序问题。

数据库在通过连接两张或多张表返回记录时,首先根据连接条件生成一张临时表,然后,where条件过滤临时表,最后,将结果返回给用户。
这里就说的很明白了,SQL语句执行先使用on条件,然后,使用where条件。

这里,有必要再次明确一下left join...on... 语法的准确含义。

LEFT JOIN 关键字从左表(table1)返回所有的行,即使右表(table2)中没有匹配。如果右表中没有匹配,则结果为 NULL。
展开来解释一下就是:左表是主表,总是全部返回,而右表的结果是根据on条件来决定的。如果on条件为真,那么,就返回匹配上的右表结果,如果on条件为假,那么就把右表的结果用null填充。
这里的on条件不仅限于一个,也可以是多个。

有了上面的基础知识,就可以进一步去理解阐述了。

  • 如果b.name='apple'作为where条件,那么,按照sql语句的执行流程,首先生成连接查询临时表结果,这一步是没有问题的,然后使用where条件过滤,这时候,b表中并没有符合条件的数据,这样,所有数据就被过滤掉了。返回的结果,就不符合预期了。
  • 如果b.name='apple'作为on条件,那么,按照sql语句的执行流程,首先生成连接查询临时表结果,这一步也是没有问题的,依然,能达到我们的预期。

总结

有时候,很简单的问题,却并不简单。回头看,还是对基础概念把握的不够明晰,有模糊的地方。
这里的on条件和where条件的作用是完全不同的。on条件不具备过滤作用,只做判断。而where条件不仅做判断,还要对结果进行过滤。

参考自:https://www.cnblogs.com/dancesir/p/7600265.html

你可能感兴趣的:(SQL语句中连接on条件和where条件的执行顺序)