在mysql中同时使用left join on 和where 的查询结果分析

以前用惯了oracle,在处理左连接和有链接的时候,只需要在sql中添加(+)就可以了,但是在mysql中,将left join或者right join 与 on 和 where进行联合使用的时候,不同的联合用法,得到的却是不同的结果。现在记录一下。

假设有左表tb_oder,该表有order_id和user_id字段;有右表tb_user,该表有user_id和user_name两个字段,两个表使用user_id进行关联。

SQL1:
select o.order_id,o.user_id,u.user_id,u.user_name
from tb_order o LEFT JOIN tb_user u
on o.user_id = u.user_id;
这是最常规的用法,如果右表中没有对应的数据,则结果集中显示为空。

SQL2:
select o.order_id,o.user_id,u.user_id,u.user_name
from tb_order o LEFT JOIN tb_user u
on o.user_id = u.user_id
and u.user_id > 10;
这个对右表进行筛选之后再与左表关联的,所以,即便右表和左表中都有user_id<10的数据,user_name的显示结果也为空。

SQL3
select o.order_id,o.user_id,u.user_id,u.user_name
from tb_order o LEFT JOIN tb_user u
on o.user_id = u.user_id
and o.order_id > 10;

SQL4:
select o.order_id,o.user_id,u.user_id,u.user_name
from tb_order o LEFT JOIN tb_user u
on o.user_id = u.user_id
and o.user_id > 10;
这两个语句貌似是对左表进行筛选之后,再与右表关联,但是他并不是这样的。实际上,无论如何,左表tb_order中的数据都会全部显示,对左表进行限定的条件下,对应的右表中符合关联条件的内容却被强制设置为空。这两个语句的效果与SQL2是一样的,但是效果却难以理解,一般不建议这么写。

SQL5:
select o.order_id,o.user_id,u.user_id,u.user_name
from tb_order o LEFT JOIN tb_user u
on o.user_id = u.user_id
where u.user_id > 10;

SQL6:
select o.order_id,o.user_id,u.user_id,u.user_name
from tb_order o LEFT JOIN tb_user u
on o.user_id = u.user_id
where o.user_id > 10;
这两个语句的结果更有意思,他们的效果是一样的,就是,把使用left join on 进行关联的结果集再按照where条件进行筛选。

按照上面的分析,似乎,这样的SQL中,并无一个比较易懂的,首先去筛选左表的内容,然后再与右表进行匹配的办法。较好的办法就是,对左表用子查询进行筛选,如果无法理解上面的left join on where 中的where的使用方式,也可以对右表用子查询进行筛选。
SQL如下:
select o.order_id,o.user_id,u.user_id,u.user_name
from ( select * from tb_order where order_id > 10 ) o LEFT JOIN tb_user u
on o.user_id = u.user_id;

select o.order_id,o.user_id,u.user_id,u.user_name
from ( select * from tb_order where order_id > 10 ) o LEFT JOIN (select * from tb_user where user_id > 20) u
on o.user_id = u.user_id;
原文地址:https://www.cnblogs.com/babyha/p/13932348.html