自己对mysql中的Join的理解
生活随笔
收集整理的這篇文章主要介紹了
自己对mysql中的Join的理解
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
注: 本文是我自己的學習思路。自己的理解還很淺,而且很有可能是錯的。文章只是輔助自己理解。若有看官閱讀了,請指出我的錯誤,但請不要侮辱我。
cityjoin表:
+----+-----------+-------------+-----------+------------+
| id | Name????? | CountryCode | District? | Population |
+----+-----------+-------------+-----------+------------+
|? 1 | Shanghai? | CHN???????? | Shanghai? |??? 9696300 |
|? 2 | Peking??? | CHN???????? | Peking??? |??? 7472000 |
|? 3 | Chongqing | CHN???????? | Chongqing |??? 6351600 |
|? 4 | Tianjin?? | CHN???????? | Tianjin?? |??? 5286800 |
|? 5 | Wuhan???? | CHN???????? | Hubei???? |??? 4344600 |
+----+-----------+-------------+-----------+------------+
?
?countryjoin表:
?+------+-------------+---------------+-------------+------------+
| Code | Name??????? | Continent???? | SurfaceArea | Population |
+------+-------------+---------------+-------------+------------+
| ABW? | Aruba?????? | North America |????? 193.00 |???? 103000 |
| AFG? | Afghanistan | Asia????????? |?? 652090.00 |?? 22720000 |
| AGO? | Angola????? | Africa??????? |? 1246700.00 |?? 12878000 |
| AIA? | Anguilla??? | North America |?????? 96.00 |?????? 8000 |
| ALB? | Albania???? | Europe??????? |??? 28748.00 |??? 3401200 |
| CHN? | China?????? | Asia????????? |? 9600000.00 |? 130000000 |
+------+-------------+---------------+-------------+------------+
?
?1. Join
?select cityjoin.id, cityjoin.Name, countryjoin.Name c_Name from cityjoin left join countryjoin on cityjoin.Name=cityjoin.District and countryjoin.Code=cityjoin.CountryCode;
?我們要從 cityjoin 表要選出的記錄(不過只顯示id和Name)要滿足的條件是
?cityjoin.Name=cityjoin.District
?AND
?countryjoin.Code=cityjoin.CountryCode;
?怎么理解?就是說我們把左右兩表作了連接,要顯示的就是city表中的直轄市,并且,這個直轄市所在的國家要在countryjoin表中對應起來,最后把完全滿足于這個條件的左右表需要的記錄返回過來。
?
?返回的記錄為:
?+----+-----------+--------+
| id | Name????? | c_Name |
+----+-----------+--------+
|? 1 | Shanghai? | China? |
|? 2 | Peking??? | China? |
|? 3 | Chongqing | China? |
|? 4 | Tianjin?? | China? |
+----+-----------+--------+
上述是最正確的情況,也滿足了需求。現在來破壞條件。
首先試著在cityjoin加上一條數據,滿足cityjoin.Name=cityjoin.District,不過讓這個直轄市所在的國家在country表中找不到。
INSERT INTO cityjoin VALUES('SaltLake', 'USA', 'SaltLake', 500000);
此時的cityjoin表:
+----+-----------+-------------+-----------+------------+
| id | Name????? | CountryCode | District? | Population |
+----+-----------+-------------+-----------+------------+
|? 1 | Shanghai? | CHN???????? | Shanghai? |??? 9696300 |
|? 2 | Peking??? | CHN???????? | Peking??? |??? 7472000 |
|? 3 | Chongqing | CHN???????? | Chongqing |??? 6351600 |
|? 4 | Tianjin?? | CHN???????? | Tianjin?? |??? 5286800 |
|? 5 | Wuhan???? | CHN???????? | Hubei???? |??? 4344600 |
|? 6 | SaltLake? | USA???????? | SaltLake? |???? 500000 |
+----+-----------+-------------+-----------+------------+
然后重新執行上面的select語句,結果仍舊一樣。
+----+-----------+--------+
| id | Name????? | c_Name |
+----+-----------+--------+
|? 1 | Shanghai? | China? |
|? 2 | Peking??? | China? |
|? 3 | Chongqing | China? |
|? 4 | Tianjin?? | China? |
+----+-----------+--------+
新加入的SaltLake,滿足了直轄市的條件,不過對應的國家在country那邊是找不到的。所以不予顯示: 考慮我們要列擁有id,Name,c_Name3個列的表出來,下面全是直轄市。不過如果我們將SaltLake的東西要顯示出來,那么c_Name這里該顯示什么東西?沒錯,就是Null。顯然join不和Null打交道。換而言之,我們用join連接時,左右表中任意可能出現Null的記錄,都不會被返回。那么如果我想顯示呢?如果想要顯示沒有對應country的直轄市,left join就派上用場了。
2. Left/Right Join
依然是上面加入SaltLake的表,查詢語句中join換為left join.結果如下:
+----+-----------+--------+
| id | Name????? | c_Name |
+----+-----------+--------+
|? 1 | Shanghai? | China? |
|? 2 | Peking??? | China? |
|? 3 | Chongqing | China? |
|? 4 | Tianjin?? | China? |
|? 5 | Wuhan???? | NULL?? |
|? 6 | SaltLake? | NULL?? |
+----+-----------+--------+
恩?按照之前的設想應該把直轄市SaltLake加入進去,在c_Name顯示NULL才對。怎么Wuhan也加進來了?
來看看LEFT JOIN的解釋:
LEFT JOIN 關鍵字會從左表 (table_name1) 那里返回所有的行,即使在右表 (table_name2) 中沒有匹配的行。
這下清楚了,之前的理解是有誤的。我們的join table on 后面的條件是一個整體,如果分開來看,那就大錯特錯了。
再試試right join
+------+-----------+-------------+
| id?? | Name????? | c_Name????? |
+------+-----------+-------------+
|??? 1 | Shanghai? | China?????? |
|??? 2 | Peking??? | China?????? |
|??? 3 | Chongqing | China?????? |
|??? 4 | Tianjin?? | China?????? |
| NULL | NULL????? | Aruba?????? |
| NULL | NULL????? | Afghanistan |
| NULL | NULL????? | Angola????? |
| NULL | NULL????? | Anguilla??? |
| NULL | NULL????? | Albania???? |
+------+-----------+-------------+
我們可以總結出一句話: join是精確篩選,而left/right join則是在精確篩選的基礎之上,將左/右 表的記錄再單獨塞進去,然后在 右/左表的列名下面留NULL。
我們可以用where字句把left join的結果集進行逆向篩選:
?select cityjoin.id, cityjoin.Name, countryjoin.Name c_Name
?from cityjoin
?left join countryjoin
?on cityjoin.Name=cityjoin.District and countryjoin.Code=cityjoin.CountryCode
?where cityjoin.Name=cityjoin.District and countryjoin.Code=cityjoin.CountryCode;
?
結果如下:
+----+-----------+--------+
| id | Name????? | c_Name |
+----+-----------+--------+
|? 1 | Shanghai? | China? |
|? 2 | Peking??? | China? |
|? 3 | Chongqing | China? |
|? 4 | Tianjin?? | China? |
+----+-----------+--------+
cityjoin表:
+----+-----------+-------------+-----------+------------+
| id | Name????? | CountryCode | District? | Population |
+----+-----------+-------------+-----------+------------+
|? 1 | Shanghai? | CHN???????? | Shanghai? |??? 9696300 |
|? 2 | Peking??? | CHN???????? | Peking??? |??? 7472000 |
|? 3 | Chongqing | CHN???????? | Chongqing |??? 6351600 |
|? 4 | Tianjin?? | CHN???????? | Tianjin?? |??? 5286800 |
|? 5 | Wuhan???? | CHN???????? | Hubei???? |??? 4344600 |
+----+-----------+-------------+-----------+------------+
?
?countryjoin表:
?+------+-------------+---------------+-------------+------------+
| Code | Name??????? | Continent???? | SurfaceArea | Population |
+------+-------------+---------------+-------------+------------+
| ABW? | Aruba?????? | North America |????? 193.00 |???? 103000 |
| AFG? | Afghanistan | Asia????????? |?? 652090.00 |?? 22720000 |
| AGO? | Angola????? | Africa??????? |? 1246700.00 |?? 12878000 |
| AIA? | Anguilla??? | North America |?????? 96.00 |?????? 8000 |
| ALB? | Albania???? | Europe??????? |??? 28748.00 |??? 3401200 |
| CHN? | China?????? | Asia????????? |? 9600000.00 |? 130000000 |
+------+-------------+---------------+-------------+------------+
?
?1. Join
?select cityjoin.id, cityjoin.Name, countryjoin.Name c_Name from cityjoin left join countryjoin on cityjoin.Name=cityjoin.District and countryjoin.Code=cityjoin.CountryCode;
?我們要從 cityjoin 表要選出的記錄(不過只顯示id和Name)要滿足的條件是
?cityjoin.Name=cityjoin.District
?AND
?countryjoin.Code=cityjoin.CountryCode;
?怎么理解?就是說我們把左右兩表作了連接,要顯示的就是city表中的直轄市,并且,這個直轄市所在的國家要在countryjoin表中對應起來,最后把完全滿足于這個條件的左右表需要的記錄返回過來。
?
?返回的記錄為:
?+----+-----------+--------+
| id | Name????? | c_Name |
+----+-----------+--------+
|? 1 | Shanghai? | China? |
|? 2 | Peking??? | China? |
|? 3 | Chongqing | China? |
|? 4 | Tianjin?? | China? |
+----+-----------+--------+
上述是最正確的情況,也滿足了需求。現在來破壞條件。
首先試著在cityjoin加上一條數據,滿足cityjoin.Name=cityjoin.District,不過讓這個直轄市所在的國家在country表中找不到。
INSERT INTO cityjoin VALUES('SaltLake', 'USA', 'SaltLake', 500000);
此時的cityjoin表:
+----+-----------+-------------+-----------+------------+
| id | Name????? | CountryCode | District? | Population |
+----+-----------+-------------+-----------+------------+
|? 1 | Shanghai? | CHN???????? | Shanghai? |??? 9696300 |
|? 2 | Peking??? | CHN???????? | Peking??? |??? 7472000 |
|? 3 | Chongqing | CHN???????? | Chongqing |??? 6351600 |
|? 4 | Tianjin?? | CHN???????? | Tianjin?? |??? 5286800 |
|? 5 | Wuhan???? | CHN???????? | Hubei???? |??? 4344600 |
|? 6 | SaltLake? | USA???????? | SaltLake? |???? 500000 |
+----+-----------+-------------+-----------+------------+
然后重新執行上面的select語句,結果仍舊一樣。
+----+-----------+--------+
| id | Name????? | c_Name |
+----+-----------+--------+
|? 1 | Shanghai? | China? |
|? 2 | Peking??? | China? |
|? 3 | Chongqing | China? |
|? 4 | Tianjin?? | China? |
+----+-----------+--------+
新加入的SaltLake,滿足了直轄市的條件,不過對應的國家在country那邊是找不到的。所以不予顯示: 考慮我們要列擁有id,Name,c_Name3個列的表出來,下面全是直轄市。不過如果我們將SaltLake的東西要顯示出來,那么c_Name這里該顯示什么東西?沒錯,就是Null。顯然join不和Null打交道。換而言之,我們用join連接時,左右表中任意可能出現Null的記錄,都不會被返回。那么如果我想顯示呢?如果想要顯示沒有對應country的直轄市,left join就派上用場了。
2. Left/Right Join
依然是上面加入SaltLake的表,查詢語句中join換為left join.結果如下:
+----+-----------+--------+
| id | Name????? | c_Name |
+----+-----------+--------+
|? 1 | Shanghai? | China? |
|? 2 | Peking??? | China? |
|? 3 | Chongqing | China? |
|? 4 | Tianjin?? | China? |
|? 5 | Wuhan???? | NULL?? |
|? 6 | SaltLake? | NULL?? |
+----+-----------+--------+
恩?按照之前的設想應該把直轄市SaltLake加入進去,在c_Name顯示NULL才對。怎么Wuhan也加進來了?
來看看LEFT JOIN的解釋:
LEFT JOIN 關鍵字會從左表 (table_name1) 那里返回所有的行,即使在右表 (table_name2) 中沒有匹配的行。
這下清楚了,之前的理解是有誤的。我們的join table on 后面的條件是一個整體,如果分開來看,那就大錯特錯了。
再試試right join
+------+-----------+-------------+
| id?? | Name????? | c_Name????? |
+------+-----------+-------------+
|??? 1 | Shanghai? | China?????? |
|??? 2 | Peking??? | China?????? |
|??? 3 | Chongqing | China?????? |
|??? 4 | Tianjin?? | China?????? |
| NULL | NULL????? | Aruba?????? |
| NULL | NULL????? | Afghanistan |
| NULL | NULL????? | Angola????? |
| NULL | NULL????? | Anguilla??? |
| NULL | NULL????? | Albania???? |
+------+-----------+-------------+
我們可以總結出一句話: join是精確篩選,而left/right join則是在精確篩選的基礎之上,將左/右 表的記錄再單獨塞進去,然后在 右/左表的列名下面留NULL。
我們可以用where字句把left join的結果集進行逆向篩選:
?select cityjoin.id, cityjoin.Name, countryjoin.Name c_Name
?from cityjoin
?left join countryjoin
?on cityjoin.Name=cityjoin.District and countryjoin.Code=cityjoin.CountryCode
?where cityjoin.Name=cityjoin.District and countryjoin.Code=cityjoin.CountryCode;
?
結果如下:
+----+-----------+--------+
| id | Name????? | c_Name |
+----+-----------+--------+
|? 1 | Shanghai? | China? |
|? 2 | Peking??? | China? |
|? 3 | Chongqing | China? |
|? 4 | Tianjin?? | China? |
+----+-----------+--------+
總結
以上是生活随笔為你收集整理的自己对mysql中的Join的理解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 电子血压计
- 下一篇: [DB] From Leng,Oracl