1. 程式人生 > >一個sql問題深入理解左連線

一個sql問題深入理解左連線

資料準備

  • 1.新建一個學生表t_student 如下 del_falg = ‘1’ ,’表示邏輯刪除’
    學生表

  • 2.新建課程表 t_course
    課程表

  • 3.新建 學生選課表 r_course_student
    課程學生中間表

  • 4.上面的表結構並不複雜,需要關注的一個點是 4號學生已經被刪除了,當然他的選課關係表也刪除了

SELECT t.name 學生姓名  ,cs.cid 課程id , t.del_flag 學生刪除標誌,cs.del_flag 學生課程關係刪除標誌 FROM t_student  t
LEFT JOIN r_course_student cs ON t.id = cs.sid
AND cs.del_flag = '0' WHERE t.del_flag = '0'

查詢sql1

SELECT t.name 學生姓名  ,cs.cid 課程id , t.del_flag 學生刪除標誌,cs.del_flag 學生課程關係刪除標誌 FROM t_student  t
LEFT JOIN r_course_student cs ON t.id = cs.sid AND cs.del_flag = '0' AND t.del_flag = '0'

結果2

發現錯誤

可以發現,已經被刪除的學生 和選課資訊被查詢出來了,為什麼?
就是主表的條件寫在on後面導致的。

左連線遵循的一個原則是,主表的資訊一定會顯示出來,而從表可能沒有主表所對應的記錄,相應的列就置為null ,第一條sql滿足我們預期的結果,下面分析一下 兩條sql的執行過程。

過程分析

  • 第一條:

    • 1.t.id = cs.sid AND cs.del_flag = ‘0’通過這個條件生成中間臨時表
    • 2.通過WHERE t.del_flag = ‘0’ 對臨時表進行篩選,返回正確結果
  • 第二條:

    • ON t.id = cs.sid AND cs.del_flag = ‘0’ AND t.del_flag = ‘0’生成 臨時表,但是連線原則是主表的記錄一定會被查詢出來,所以不論on後面的條件對主表怎樣過濾,都是無效的,無效的,無效的,所以造成了錯誤的結果。。

結論

  • 1.使用連線時,on後面一定不要接過濾主表的條件,否則可能造成難以預料的後果,過濾主表的條件應該放在where後面,對生成的中間結果集進行過濾。當生成中間結果集後,就已經沒有連線的概念了,這個中間資料就像是一張全新的表一樣。
  • 2.過濾從表的條件(也包括連線條件)可以儘量寫在on後面,這樣在生成中間表時,就少了很多不必要的資料、

相關推薦

no