這裡我先給出乙個場景,並丟擲兩個問題,如果你都能答對那這篇文章就不用看了。
那麼現在有兩個需求:
找出每個班級的名稱及其對應的女同學數量對於需求1,大多數人不假思索就能想出如下兩種sql寫法找出一班的同學總數
正確 ✔
select c.name, count(s.name) as num
from classes c left join students s
on s.class_id = c.id
and s.gender = 'f'
group by c.name
或者
錯誤❌
select c.name, count(s.name) as num
from classes c left join students s
on s.class_id = c.id
where s.gender = 'f'
group by c.name
對於需求2,大多數人也可以不假思索的想出如下兩種sql寫法,請問哪種是對的?
正確 ✔
select c.name, count(s.name) as num
from classes c left join students s
on s.class_id = c.id
where c.name = '一班'
group by c.name
或者
錯誤❌
select c.name, count(s.name) as num
from classes c left join students s
on s.class_id = c.id
and c.name = '一班'
group by c.name
mysql 對於left join的採用類似巢狀迴圈的方式來進行從處理,以下面的語句為例:
select * from lt left join rt on p1(lt,rt)) where p2(lt,rt)
其中p1是on過濾條件,缺失則認為是true,p2是where過濾條件,缺失也認為是true,該語句的執行邏輯可以描述為:
for each row lt in lt
b=true;// lt在rt中有對應的行
} if (!b)
}}
當然,實際情況中mysql會使用buffer的方式進行優化,減少行比較次數,不過這不影響關鍵的執行流程,不在本文討論範圍之內。
從這個偽**中,我們可以看出兩點:
下面展開兩個需求的錯誤語句的執行結果和錯誤原因:需求1
需求2
需求1由於在where條件中對右表限制,導致資料缺失(四班應該有個為0的結果)
需求2由於在on條件中對左表限制,導致資料多餘(其他班的結果也出來了,還是錯的)
通過上面的問題現象和分析,可以得出了結論:在left join語句中,左表過濾必須放where條件中,右表過濾必須放on條件中,這樣結果才能不多不少,剛剛好。
sql 看似簡單,其實也有很多細節原理在裡面,乙個小小的混淆就會造成結果與預期不符,所以平時要注意這些細節原理,避免關鍵時候出錯。
python避坑 python避坑指南,持續更新
python安裝,匯入,和使用避坑指南,持續更新 bestmrright原創 因為python庫太多,開發者眾多,有些庫引用了其他庫,隨著其他庫不斷更新,有些類和方法會修改,有些庫作廢,有些庫被收入進python,所以使用時候經常有坑需要迴避。在此建貼,持續更新,以便後來者避坑,希望來著補充。安裝坑...
mysql left join的坑和優化經驗
參考文章 create table classes id int 11 not null primary key,name varchar 32 not null insert into classes id name values 1,一班 2,二班 3,三班 4,四班 create table ...
C避坑指南
int型 絕對值在10 9範圍內的整數都可以定義成int型。long long型 如果long long型賦值大於2 31 1的初值,則需要在初值後面加上ll,否則會編譯錯誤。float double輸入輸出格式 使用printf f c 語句時,f是float和double型的輸出格式。而在使用s...