21 SQL Join1
1. 定義
維基百科:SQL 中的
連線
(Join)語句用於將資料庫中的兩個或多個表組合起來,由連線生成的資料集合,可以被儲存為表,也可以被當成表來使用。
解釋:連線操作是 SQL 操作的重中之中,是關係資料庫中體現
關係
的核心指令;連線操常用於合併擁有關聯關係的兩表或者多表,並從中獲取資料。
2. 前言
前面的小節中,我們談到了外來鍵
是體現資料關係中的核心點,那麼定義好的外來鍵如何被使用了?
連線操作是使用外來鍵最主要的方式,通過連線可以將兩個或多個擁有外來鍵關聯的資料表的資料進行合併,然後選擇需要的資料欄位。
SQL 有五種 連線 方式:內連線(Inner),全外連線(Full Outer),左外連線(Left Outer),右外連線(Right Outer)和交叉連線(Cross)。
本小節,我們將學習五種連線中比較基礎的交叉連線
和內連線
。
本小節測試資料如下,請先在資料庫中執行:
DROP TABLE IF EXISTS imooc_class;
CREATE TABLE imooc_class
(
id int PRIMARY KEY,
class_name varchar(20)
);
INSERT INTO imooc_class(id,class_name) VALUES(1,'SQL必知必會'), (2,'C語言入門'),
(3,'JAVA高效程式設計'),(4,'JVM花落知多少');
DROP TABLE IF EXISTS imooc_user;
CREATE TABLE imooc_user
(
id int PRIMARY KEY,
username varchar(20),
class_id int references imooc_class(id)
);
INSERT INTO imooc_user(id,username,class_id) VALUES(1,'pedro', 1), (2,'peter', 1),
(3,'faker', 2), (4,'lucy', 4),(5,'jery', NULL);
說明: 我們分別新建了 imooc_class 表——課程表,和 imooc_user 表——使用者表;其中 imooc_user 表中的 class_id 作為外來鍵指向 imooc_class 的主鍵 id;若 class_id 為 NULL 則表示該使用者暫時還未加入任何課程,否則 class_id 表示使用者參加課程的 id 。
注意: 為了保證 SQL 可以在每個資料庫中執行,所以沒有使用 AUTO_INCREMENT 等約束,但真實業務場景下請新增上。
3. SQL Cross Join
交叉連線(Cross Join),又稱笛卡爾連線(Cartesian Join),其作用是返回兩表的笛卡爾積。
交叉連線可用於任意兩表進行連線,即使兩表之間不存在關聯關係。
3.1 例1 笛卡爾積
請書寫 SQL 語句得到imooc_class
和imooc_user
兩表的笛卡爾積。
分析:
使用 Select 搭配 Cross Join 得到兩表的笛卡爾積即可。
語句:
SELECT * FROM imooc_class CROSS JOIN imooc_user;
+----+---------------+----+----------+----------+
| id | class_name | id | username | class_id |
+----+---------------+----+----------+----------+
| 1 | SQL必知必會 | 1 | pedro | 1 |
| 2 | C語言入門 | 1 | pedro | 1 |
| 3 | JAVA高效程式設計 | 1 | pedro | 1 |
| 4 | JVM花落知多少 | 1 | pedro | 1 |
| 1 | SQL必知必會 | 2 | peter | 1 |
| 2 | C語言入門 | 2 | peter | 1 |
| 3 | JAVA高效程式設計 | 2 | peter | 1 |
| 4 | JVM花落知多少 | 2 | peter | 1 |
| 1 | SQL必知必會 | 3 | faker | 2 |
| 2 | C語言入門 | 3 | faker | 2 |
| 3 | JAVA高效程式設計 | 3 | faker | 2 |
| 4 | JVM花落知多少 | 3 | faker | 2 |
| 1 | SQL必知必會 | 4 | lucy | 4 |
| 2 | C語言入門 | 4 | lucy | 4 |
| 3 | JAVA高效程式設計 | 4 | lucy | 4 |
| 4 | JVM花落知多少 | 4 | lucy | 4 |
| 1 | SQL必知必會 | 5 | jery | <null> |
| 2 | C語言入門 | 5 | jery | <null> |
| 3 | JAVA高效程式設計 | 5 | jery | <null> |
| 4 | JVM花落知多少 | 5 | jery | <null> |
+----+---------------+----+----------+----------+
從結果中可以看出,交叉連線就是將一張表的每一條記錄與另一張表的每一條記錄進行連線成為一條新記錄,排列組合完畢後得到兩張表的笛卡爾積。
交叉連線還可以通過隱式的連線方式來實現:
SELECT * FROM imooc_class,imooc_user;
4. SQL Inner Join
內連線(Inner Join),是將一張表的每一條記錄與另一張表的每一行記錄進行比較,得到兩張表匹配的記錄集合。
維恩圖表示如下:
圖中深色部分便是最後的返回結果。
4.1 例2 內連線
請書寫 SQL 語句,返回imooc_class
和imooc_user
兩表的內連線集合。
分析:
使用 Select 搭配 Inner Join 即可。
語句
SELECT * FROM imooc_user INNER JOIN imooc_class ON imooc_user.class_id = imooc_class.id;
結果如下:
+----+----------+----------+----+---------------+
| id | username | class_id | id | class_name |
+----+----------+----------+----+---------------+
| 1 | pedro | 1 | 1 | SQL必知必會 |
| 2 | peter | 1 | 1 | SQL必知必會 |
| 3 | faker | 2 | 2 | C語言入門 |
| 4 | lucy | 4 | 4 | JVM花落知多少 |
+----+----------+----------+----+---------------+
一般情況下,交叉連線是預設的連線方式,因此我們可以省略INNER
關鍵字:
SELECT * FROM imooc_user JOIN imooc_class ON imooc_user.class_id = imooc_class.id;
這樣也能得到同樣的結果;使用 Join 和 On 關鍵字可以顯式連線兩表,我們也可以通過 Where 進行隱式的連線:
SELECT * FROM imooc_user, imooc_class WHERE imooc_user.class_id = imooc_class.id;
5. 小結
- 交叉連線和內連線真實的使用場景其實較少,不過使用也比較簡單,多加操練記住即可。
- 本小節的例子中,imooc_user 與 imooc_class 的外來鍵方式其實是不推薦的,真實業務中的外來鍵方式將在後面的實戰部分介紹。