LEFT JOIN、Right、Full后ON和WHERE的区别

  今天在工作的时候碰到了一个问题,A表B表left join后在on后面关于A表的条件过滤语句没起到我想要的过滤作用,还是对左连接等理解的不够呀。

SELECT * FROM student;
SELECT * FROM class;
以下是两张表的查询结果:
          
      student表                    class表

                

  先来看一下student表和class表根据cla_id左连接返回的结果

SELECT * FROM student stu 
LEFT JOIN class cla 
ON stu.cla_id = cla.cla_id
返回的结果也正如我的预期,那么就再来看看加上一个stu_id
=1条件后返回的结果 SELECT * FROM student stu LEFT JOIN class cla ON stu.cla_id = cla.cla_id AND stu.stu_id=1
  我当时怎么也想不明白,天怎么会返回四条记录,我不是在后面加了个stu_id=1的条件吗?不是过滤了student表应该只返回第一条数据吗?当时听一些人说不管on后面跟什么条件,
左表的数据会全部查出来,因此要想过滤需要把条件放到where后面比如把SQL改成这样:
SELECT * FROM student stu LEFT JOIN class cla ON stu.cla_id = cla.cla_id WHERE stu.stu_id=1   那么on和where的区别就在于:   on条件是在生成临时表时使用的条件,它不管on中的条件是否为真,都会返回左边表中的记录,而where条件是在临时表生成好后,再对临时表进行过滤的条件。而且除了stu_id=1的
那条记录,class表中字段不满足过滤条件的记录(即使被关联到了)全是NULL,所以on后面的语句最好只写两个表相关联的语句,并不能做单方面的过滤。也可以这么简单的理解,以坐标
为主,先查询出左表的全部记录,然后关联右表,将符合条件的记录的数据填充进查询出来的结果。
right joinfull join 具有相同的特性,但是inner join不同,它可以在on 那
里做过滤处理,也就是说放在on后面和where后面作用是一样的。      顺便提一下,当我们对一个字段进行了处理重命名后,就直接在where语句后面用做过滤条件的话,会报不能识别的列。下面我以mysql的方言为例。   
SELECT id, begintime, from_unixtime((UNIX_TIMESTAMP(begintime)*1000+auctiontime)/1000) AS endtime FROM auctioncommendity where endtime>NOW();  这条语句会提示endtime是不能识别的列,要在这个查询作为一个结果集在外围where条件做过滤才可行,例如这样:   select a.* from (SELECT id, begintime, from_unixtime((UNIX_TIMESTAMP(begintime)*1000+auctiontime)/1000) AS endtime FROM auctioncommendity ) a where endtime>NOW();   但是又有些情况下是可以的,比如order by 和group后在having后面做过滤不需要用到子查询就可以直接使用经过处理的重命名字段。关于原因....先睡觉,以后再找      话说写博客可真花时间呀.....

 

posted @ 2015-08-05 01:33  menz_i  阅读(2350)  评论(2编辑  收藏  举报