MySQL LEFT JOIN 左表缺失與重複

2021-10-03 04:02:02 字數 1969 閱讀 2781

mysql 使用left join 後應該得到的結果是左表所有內容,以及匹配到的右表內容(未匹配的留空),但是在實際使用的時候會出現左表內容不全的情況,這是不應該的,出現這種情況的原因可能是篩選條件的位置放錯了。

比如現在有兩張表:

sell (銷售)表:

iddate

profit

0001

2019-01-01

3.50001

2019-01-02

3.50002

2019-01-02

50003

2019-01-01

60003

2019-01-03

3info(商品資訊)表:

idname

sellprice

0001

洗髮露7

0002

火鍋10

0003

速食麵10

很顯然這兩張表以id作為鍵連線在一起

select sell.id, info.name, 

sell.date, sell.profit from sell

left join info on info.id=sell.id

這時應該得到正常的結果

idname

date

profit

0001

洗髮露2019-01-01

3.50001

洗髮露2019-01-02

3.50002

火鍋2019-01-02

50003

速食麵2019-01-01

60003

速食麵2019-01-03

3這種id多對一的情形一般沒有問題,除非你在where條件中對left join的目標表進行了限制,這就是下面的情形

現在我想看2019-01-01這一天所有商品的利潤,無論有沒有利潤我都想讓它顯示出來,所以以info表為左表

select info.id, info.name, sum(sell.profit) as profit from info

left join sell on sell.id=info.id

where sell.date="2019-01-01"

group by info.id

這樣得出的結果是

idname

profit

0001

洗髮露3.5

0003

速食麵6

0002號商品不見了,因為在篩選條件where sell.date="2019-01-01"中它被篩掉了,出來的結果就不是一張完整的左表。篩選條件的正確位置應該是left join 語句的on條件或者left join一張臨時select出的表,例如

left join sell on sell.id=info.id and sell.date="2019-01-01"

或者left join (select * from sell where sell.date="2019-01-01") lt on lt.id=info.id

上面的缺失情況實際是種id一對多的場景,這種情況下還有可能出現左表行數比原來還要多的情況, 原因是沒有進行group by聚合處理,而乙個id匹配到了多個結果都被保留了下來

除此之外還有一種比較坑的情況,發生在存在多個left join的情況,比如在id列上同時left join a表和b表,都是一對多的情況。id=0005的行數匹配到了3個a表中的行和5個b表中的行,那麼最後的結果是什麼樣子呢?如果不做聚合的話,我沒記錯的話會出現類似笛卡爾積的情況,即使做聚合也是對錯誤的結果聚合。解決辦法是在left join中就提前做好聚合,使得匹配是一對一的。

無論多對一匹配還是一對多匹配都有可能出現因為篩選條件位置不對而引起的缺失,要注意篩選的作用範圍(作用於最後結果,還是連線的臨時表),以及sql語句的執行順序。

MySQL left join 避坑指南

這裡我先給出乙個場景,並丟擲兩個問題,如果你都能答對那這篇文章就不用看了。那麼現在有兩個需求 找出每個班級的名稱及其對應的女同學數量 找出一班的同學總數 對於需求1,大多數人不假思索就能想出如下兩種sql寫法 正確 select c.name,count s.name as num from cla...

MYSQl left join聯合查詢效率分析

user表 id name 1 libk 2 zyfon 3 daodao user action表 user id action 1 jump 1 kick 1 jump 2 run 4 swim sql select id,name,action from user as u left join...

MYSQl left join 聯合查詢效率分析

user表 id name 1 libk 2 zyfon 3 daodao user action表 user id action 1 jump 1 kick 1 jump 2 run 4 swim sql select id,name,action from user as u left join...