MySQL的Left、Right join(外连接)中的on条件与where条件区别
数据库通过 JOIN 连接两张或多张表返回记录时,都会生成一张中间的临时表,再将这张临时表返给用户。 对主表的筛选条件,应放在 where 条件后,如果在 on 之后,则对主表筛选来说,没有任何意义。
# on、where 执行顺序
on
的优先级,高于where
。 两者后面放置相同条件,可能会导致结果集不同,就是因为优先级所致。
# 1. mysql left join 执行原理
MySQL 中的 LEFT JOIN 是一种表连接操作,它返回左表中所有的记录,以及符合连接条件的右表中的记录,如果右表中没有符合条件的记录,则对应的列返回 NULL 值.
LEFT JOIN 的执行过程如下:
- 从左表中取出所有的记录.
- 对于左表中的每条记录,都在右表中查找符合连接条件的记录,并将左表和右表中符合条件的记录进行连接.
- 如果右表中没有符合条件的记录,则返回 NULL 值.
- 返回连接结果,其中包含左表和右表中符合条件的记录.
总的来说,LEFT JOIN 是通过将左表的所有记录和右表中符合条件的记录进行连接来实现的,如果右表中没有符合条件的记录,则对应的列返回 NULL 值
# 使用示例
table1:
id | num |
---|---|
1 | 111 |
2 | 222 |
table2:
num | name |
---|---|
111 | first |
222 | second |
执行如下两条查询:
sql1:
SELECT
a.id,
a.num,
b.NAME
FROM
table1 a
LEFT JOIN table2 b ON ( a.num = b.num AND b.NAME = 'first' );
2
3
4
5
6
7
sql2:
SELECT
a.id,
a.num,
b.NAME
FROM
table1 a
LEFT JOIN table2 b ON ( a.num = b.num )
WHERE
b.NAME = 'first';
2
3
4
5
6
7
8
9
则,第 1 条 SQL 返回:
id | num | name |
---|---|---|
1 | 111 | first |
2 | 222 | (Null) |
第 2 条 SQL 返回:
id | num | name |
---|---|---|
1 | 111 | first |
第一条 sql 的执行流程:
首先找到 b 表的 name 为 first 的记录行
on (a.num = b.num and b.name='first')
,然后找到 a 的全部数据(left join),生成临时表返回数据。
第二个 sql 的执行流程:
先生成临时表(全量),然后执行 where 过滤
b.name=’first’
不为真的结果,最后返回数据。
因为 on 会首先过滤掉不符合条件的行,然后才会进行其它运算。
执行顺序: on > where > having
, 因此理论上 on 是最快的。
多表查询时,on 比 where 更早起作用。系统首先根据各个表之间的联接条件,把多个表整合成一个临时表,再由 where 进行过滤,之后再进行计算,计算完后再由 having 过滤。
对于 JOIN 参与的表的关联操作,如果需要不满足连接条件的行也被返回,就必需把连接条件放在 ON 后,不能放在 WHERE 后面, 如果把连接条件放在了 WHERE 后面,那么所有的 LEFT、RIGHT 等操作将不起任何作用,对于这种情况,它的效果就完全等同于 INNER 连接。
# 结论
on
是在生成临时表的时候使用的条件,不管 on 的条件是否起到作用,都会返回左表 (主表) 的行。
where
则是在生成临时表之后使用的条件,此时已经不管是否使用了left join
了,只要条件不为真的行,全部过滤。
# Tips:
所有的 join 条件必需放在 ON 后面。 否则前面的 LEFT、RIGHT 关联将作为摆设,不起任何作用。
# mysql 中 where 和 on 不同点
在 MySQL 中,WHERE 和 ON 都可以用来过滤查询结果,但它们的使用场景有所不同。
- WHERE 用于过滤行级别的数据,其条件是在表连接之后进行过滤的,也就是说,WHERE 后的条件会应用到连接后的所有数据中,包括主表和从表的数据。WHERE 语句一般放在 SQL 语句的末尾,用于筛选查询结果。
- ON 用于指定两个表之间的连接条件,其条件是在表连接之前进行过滤的,也就是说,ON 后的条件只会应用到连接的两个表之间,而不会影响其他数据。ON 语句一般放在 SQL 语句的中间,用于指定表之间的连接条件。
对于主表的筛选条件,应该放在 WHERE 后面,而不是放在 ON 后面。因为主表的筛选条件是在连接之后进行的,如果把主表的筛选条件放在 ON 后面,那么会先进行表连接,再进行筛选,这样会导致查询的效率变低。而把主表的筛选条件放在 WHERE 后面,可以先进行筛选,再进行表连接,这样可以提高查询的效率。所以,一般情况下,我们建议把主表的筛选条件放在 WHERE 后面。
ON 与 where 的使用一定要注意场所: (1):ON 后面的筛选条件主要是针对的是关联表【而对于主表刷选条件不适用】。
select A.ID as AID, B.ID as BID from A left join B on A.ID = B.ID and A.ID = 3
挺诧异的吧和我们期望的结果不一样,筛选出 AID 不为 3 的数据。
但是我们也发现 AID 与 中 AID 1 于 2 对应的值为 NULL,关联表只取了满足 A 表筛刷选条件的值。
即主表条件在 on 后面时附表只取满足主表帅选条件的值、而主表还是取整表。
(2):对于主表的筛选条件应放在 where 后面,不应该放在 ON 后面
(3):对于关联表我们要区分对待。如果是要条件查询后才连接应该把查询条件放置于 ON 后。
如果是想再连接完毕后才筛选就应把条件放置于 where 后面
(4): 对于关联表我们其实可以先做子查询再做 join
- 01
- idea 热部署插件 JRebel 安装及破解,不生效问题解决04-10
- 02
- spark中代码的执行位置(Driver or Executer)12-12
- 03
- 大数据技术之 SparkStreaming12-12