mysql on和where的作用&在不同join中的作用

46 阅读2分钟

on和where是什么?

两者都是进行筛选过滤的

on: 决定 join 表的行“是否能关联”。 两个表中哪些行可以匹配(关联)

where: 对结果行做最终过滤。在 from 和 join 执行完成后,执行 where,对当前结果做条件行级过滤。

where 是“结果过滤条件”,on 是“关联阶段条件”

  • 使用场景:where对查询结果根据where条件进行筛选过滤;on 在多表 join 场景下进行 on 条件进行筛选过滤
  • 执行时机:on 和 where 同时存在的查询中,先执行on,后执行 where。on 先于 where 执行。先是 on 条件过滤,然后是 join 结果,最后 where 过滤。

inner join 和 left join

join 多表场景,mysql 会将 join on 的结果生成一张临时表,最后将临时表做 where 等条件过滤操作。on 比 where 更早起作用。

left join(左链接):会保留左表返回所有的行,即使在右表中没有匹配的行。 inner join(内连接):只返回两个表中 on 条件匹配的行

在不同 join 中的作用

inner join

inner join(要求两边都存在):查询过滤条件放在 on 中和 where 中是完全等价的。

执行引擎可能会将 on 条件和 where 条件放一起。注意:“结果集上等价,但执行顺序可能不同”。

left join

left join B on A.id = B.a_id
where B.x = 1;
left join B on A.id = B.a_id and B.x = 1;

如果要过滤整行数据,需要将 B.x = 1 放在where条件中,等A和B表 join on 完成之后再进行整行数据的筛选过滤。 如果仅仅是不想要B表的 B.x = 1 数据查询出来,但是A的数据还要保留,那么需要放在 on 条件中,保留A 行数据,B表相关字段为null。

case

A表

B表

join查询场景sql结果
left joinB表查询条件放在 onselect A.id as a_id, A.name, B.id as b_id, B.flag
from A
left join B on A.id = B.a_id and B.flag = 1
order by A.id;
B.flag = 1 只决定能不能 join 到 B。
A.id=3 没有匹配,仍然保留
left joinB表查询条件放在 whereselect A.id as a_id, A.name, B.id as b_id,B.flag
from A
left join B on A.id = B.a_id
where B.flag = 1
order by A.id;
a3记录消失未返回。
inner joinB表查询条件放在 onselect A.id as a_id, A.name, B.id as b_id, B.flag
from A
inner join B on A.id = B.a_id
where B.flag = 1
order by A.id;
where和on结果完全一致
inner joinB表查询条件放在 whereselect A.id as a_id, A.name, B.id as b_id, B.flag
from A
inner join B on A.id = B.a_id and B.flag = 1
order by A.id;
where和on结果完全一致

反join场景

select *
from A
left join B
  ON A.id = B.a_id
where B.a_id IS NULL;

执行语义:

  1. left join 匹配
  2. 没匹配到 → B.a_id = NULL
  3. where 过滤出「没匹配到的B」的A表数据