left jon連線查詢踩坑記
專案開發中經常會使用到多張表進行關聯查詢,比如left join關聯查詢。
如果有一張表A和一張表B,查詢語句 SELECT a.*,b.name from A a left join B b
On a.id = b.id 表示的含義的就是取A表獨有的資料和A表和和B表共有的資料。
如上圖所示,主表是A表,用A表去左關聯查詢B表,正常情況下會返回A表
的所有資料,不管這些資料在B表中是否存在。
自己在寫SQL語句的時候,突然發現查詢條件的位置不一樣,導致查詢結果
出現很大的差異,讓我很是疑惑。下面就來複現這個問題,首先建立兩張表A和B.
表A插入3條資料,沒有刪除,is_deleted = 1
表B插入三條資料,刪除其中兩條資料。
自己查詢的時候,想要查詢兩張表中沒有刪除的資料,於是寫了第一個查詢語句,結果如下,
自己一看這結果明顯的不對,表A是主表,會取表中的所有資料,這種查詢方式只取到一條資料。
然後換一種方式進行查詢,如下
得到了自己想要的結果,A表的所有記錄都需要,去關聯B表查詢的時候,如果匹配到就取B表
的結果,如果沒匹配到就返回null。進一步改進的查詢方式為,
為了更好的比較,自己又新增一個查詢語句,把b表的是否刪除的條件去掉,查詢結果如下
自己很好奇為什麼會出現這種狀況呢?查詢條件寫的位置不一樣,就會導致查詢結果不一致。
然後去網上尋找問題的答案,最終找到這個問題的答案:
on條件是在生成臨時表的查詢條件,不管連線的條件如何,最終都會返回主表的所有資料。
Where條件則是過濾掉臨時表的資料,即是對最終資料的過濾,如果條件不符合則就直接過濾掉。
因此
SELECT
a.*, b. NAME
FROM
table_a a
LEFT JOIN table_b b ON a.id = b.id
WHERE
a.is_deleted = 0
AND b.is_deleted = 0;
這種查詢方式就把後面兩條資料過濾掉,因為其不滿足 b.is_deleted = 0 的條件。
自己在查詢的時候,只是想使用B表的有效資料進行關聯查詢,過濾條件就不能直接寫在
Where條件中,需要寫在on後面或者是使用子查詢過濾掉。
到此問題解決。以前寫關聯查詢的時候,不需要考慮資料是否有效都是直接進行關聯查詢,
現在遇到問題,則需要特別小心,稍微不注意就會出現意想不到的錯誤,吸取這次的深刻教訓。
參考菜鳥教程中的答案。
https://www.runoob.com/w3cnote/sql-different-on-and-where.html