做項目的時候,遇到的大坑!所以在此記錄一下。
大概的表結構如下:
表a:
表b:
select a.`name` aname,b.`name` bname from a right join b on a.id = b.a_id and a.`name` in ('嘻嘻','哈哈');
產生的結果如下:
換一句sql:
select a.`name` aname,b.`name` bname from a right join b on a.id = b.a_id where a.`name` in ('嘻嘻','哈哈');
產生的結果如下:
居然一行數據都沒了!其實大概的原理是這樣的,兩表在進行關聯時,會將驅動表里面的數據先進行篩選出來,然后再對挑選出來的數據一行行到被驅動表去進行匹配關聯。。對於上面的sql來講,在mysql源碼里可以總結以下這段:
select a.`name` aname,b.`name` bname from a right join b on a.id = b.a_id where a.`name` in ('嘻嘻','哈哈');
對應於:select a.`name` aname,b.`name` bname from a right join b P1(a,b) where P2(a,b) 注:P代表的是條件,看是否滿足於總體條件
for rt in RT bool b = false for lt in LT if P1(rt,lt) if P2(rt,lt) # 拼接結果行輸出 b = true if(!b) if P2(rt,null) # 右表拼接null輸
b表行相當於是此時的rt,他拿自己的行到a表去進行匹配,滿足P1的會到P2處進行一個判斷,如果成功則拼接輸出否則不拼接,到外層的時候b已經是true;所以如果右關聯想對右表做限制,條件需要寫在where后,也就是P2
如果想對左表做限制,如果寫在where 后面,也就是如果右表的行在左表能匹配到,進入P1為true,那么在第一個P2處因為where的限制,導致行結果不輸出同時第二個P2也不輸出,那么這一行就不會加入結果集,影響我們對right join的理解,因為right join是右表全輸出,左表不匹配用null補。