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 的外鍵方式其實是不推薦的,真實業務中的外鍵方式將在后面的實戰部分介紹。