趣談JOIN操作
- 2019 年 12 月 10 日
- 筆記
在開發中我們有時需要跨表查詢某些東西
此時,我們就會使用數據庫表的連接


一塵隨手寫了個建表語句
CREATE TABLE CUSTOMER( C_ID INT NOT NULL, C_NAME VARCHAR(40) NOT NULL );


CREATE TABLE PRODUCT( P_ID INT NOT NULL, P_NAME VARCHAR(40) NOT NULL );

很快一塵就建好了另一張產品表,很顯然,產品表裏面可以存放自己想賣的手機(產品)。
同樣,產品ID(P_ID)是唯一的,標識一個產品。
師傅慧能一看,搖了搖頭

只見慧能給產品加了一個顧客ID(C_ID)字段。


在一塵思考的過程中,慧能給兩張表插入了一些數據



只見一塵隨手寫了一個SQL
SELECT C.C_NAME,P.P_NAME FROM CUSTOMER C,PRODUCT P WHERE C.C_ID = P.C_ID

慧能清了清嗓子
所謂 連接,就是兩張表根據關聯字段,組合成一個數據集。
上面兩張表的關聯字段就是 顧客ID(C_ID).
組合的數據集就好像兩張表被粘(連接)在一塊,返回一個新的數據集合。
那返回的數據集合是兩張表的所有數據嗎?並不是,是有篩選條件的。
而 內連接 指的是只連接匹配上的行,也就是說只返回兩張表匹配的記錄。
這裡的匹配指的是滿足篩選條件,下面會講。
內連接用 關鍵字 INNER JOIN(或者JOIN)表示。

只見慧能隨手寫了一個SQL
SELECT C.C_NAME,P.P_NAME FROM CUSTOMER C INNER JOIN PRODUCT P ON C.C_ID = P.C_ID
可以看到這條SQL用內連接(INNER JOIN)把客戶表(CUSTOMER)和產品表(PRODUCT)連接起來了。
連接時的篩選條件是 客戶表的ID(C.C_ID)和產品表的客戶ID(P.C_ID)相等。
篩選條件在關鍵字 ON 後面(ON C.C_ID=P.C_ID)
這個篩選條件就是篩選兩個表記錄的條件,滿足這個篩選條件就是兩張表的兩條記錄匹配上了。
內連接就是只有客戶表中的C_ID等於產品表中的C_ID,此時才會返回這兩張表中匹配的記錄。

所以很顯然,查詢的結果為:

只顯示C_NAME 和 P_NAME 是因為當時 SELECT 的時候就只選擇了這兩列。

這樣就通過內連接查出了誰買了你的手機了。除了內連接還有左連接,右連接,全連接。
其他的SQL連接
理解了內連接,其他三種連接就很好理解了。
其實用韋恩圖來表示SQL的各種連接時比較好理解的。上面說的內連接可以這樣表示:

圖片來自阮一峰的網絡日誌
可以看到,內連接(Inner Join)就是取兩個表相同的那一部分。
左連接


圖片來自阮一峰的網絡日誌
可以看到,左連接就是取左邊的表的所有記錄和右表中匹配的行。
還是用上面的表舉例。
如果讓顧客表當左邊的表(左表),產品表當右表。左表 LEFT JOIN 右表會發生什麼?
慧能隨手寫了個SQL
SELECT C.C_NAME,P.P_NAME FROM CUSTOMER C LEFT JOIN PRODUCT P ON C.C_ID = P.C_ID
慧能在腦子裡運行了一下,只見他畫了兩幅圖。


可以看到:LEFT JOIN返回左表的全部記錄和右表滿足ON條件的記錄,如果左表的記錄在右表中沒有匹配,那麼這一條記錄在右表中對應數據用NULL代替

右連接


圖片來自阮一峰的網絡日誌
可以看到,右連接就是取右邊的表的所有記錄和左表中匹配的行。
同理寫一個SQL:
SELECT C.C_NAME,P.P_NAME FROM CUSTOMER C RIGHT JOIN PRODUCT P ON C.C_ID = P.C_ID

可以看到:RIGHT JOIN返回右表的全部記錄和左表滿足ON條件的記錄,如果右表的記錄在左表中沒有匹配,那麼這一條記錄在左表中對應數據用NULL代替。

全連接


圖片來自阮一峰的網絡日誌
可以看到,全連接(Full Join)返回兩個表中所有的記錄。
按照慣例寫個SQL:
SELECT C.C_NAME,P.P_NAME FROM CUSTOMER C FULL JOIN PRODUCT P ON C.C_ID = P.C_ID

可以看到:全連接(Full Join)返回兩個表中所有的記錄,如果其中一個表的記錄在另一個表中沒有匹配記錄,那麼對面的數據用NULL代替。
注意:全連接(FULL JOIN)MySql 不支持,Oracle支持。

看着一塵高興的背影,慧能露出了欣慰的笑容。


