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后面做過濾不需要用到子查詢就可以直接使用經過處理的重命名字段。關於原因....先睡覺,以后再找      話說寫博客可真花時間呀.....

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM