在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;