SQL Join1
1. 定義
維基百科:SQL 中的
連接
(Join)語(yǔ)句用于將數(shù)據(jù)庫(kù)中的兩個(gè)或多個(gè)表組合起來(lái),由連接生成的數(shù)據(jù)集合,可以被保存為表,也可以被當(dāng)成表來(lái)使用。
慕課解釋:連接操作是 SQL 操作的重中之中,是關(guān)系數(shù)據(jù)庫(kù)中體現(xiàn)
關(guān)系
的核心指令;連接操常用于合并擁有關(guān)聯(lián)關(guān)系的兩表或者多表,并從中獲取數(shù)據(jù)。
2. 前言
前面的小節(jié)中,我們談到了外鍵
是體現(xiàn)數(shù)據(jù)關(guān)系中的核心點(diǎn),那么定義好的外鍵如何被使用了?
連接操作是使用外鍵最主要的方式,通過(guò)連接可以將兩個(gè)或多個(gè)擁有外鍵關(guān)聯(lián)的數(shù)據(jù)表的數(shù)據(jù)進(jìn)行合并,然后選擇需要的數(shù)據(jù)字段。
SQL 有五種 連接 方式:內(nèi)連接(Inner),全外連接(Full Outer),左外連接(Left Outer),右外連接(Right Outer)和交叉連接(Cross)。
本小節(jié),我們將學(xué)習(xí)五種連接中比較基礎(chǔ)的交叉連接
和內(nèi)連接
。
本小節(jié)測(cè)試數(shù)據(jù)如下,請(qǐng)先在數(shù)據(jù)庫(kù)中執(zhí)行:
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必知必會(huì)'), (2,'C語(yǔ)言入門'),
(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);
說(shuō)明: 我們分別新建了 imooc_class 表——課程表,和 imooc_user 表——用戶表;其中 imooc_user 表中的 class_id 作為外鍵指向 imooc_class 的主鍵 id;若 class_id 為 NULL 則表示該用戶暫時(shí)還未加入任何課程,否則 class_id 表示用戶參加課程的 id 。
注意: 為了保證 SQL 可以在每個(gè)數(shù)據(jù)庫(kù)中執(zhí)行,所以沒(méi)有使用 AUTO_INCREMENT 等約束,但真實(shí)業(yè)務(wù)場(chǎng)景下請(qǐng)?zhí)砑由稀?/p>
3. SQL Cross Join
交叉連接(Cross Join),又稱笛卡爾連接(Cartesian Join),其作用是返回兩表的笛卡爾積。
交叉連接可用于任意兩表進(jìn)行連接,即使兩表之間不存在關(guān)聯(lián)關(guān)系。
3.1 例1 笛卡爾積
請(qǐng)書(shū)寫(xiě) SQL 語(yǔ)句得到imooc_class
和imooc_user
兩表的笛卡爾積。
分析:
使用 Select 搭配 Cross Join 得到兩表的笛卡爾積即可。
語(yǔ)句:
SELECT * FROM imooc_class CROSS JOIN imooc_user;
+----+---------------+----+----------+----------+
| id | class_name | id | username | class_id |
+----+---------------+----+----------+----------+
| 1 | SQL必知必會(huì) | 1 | pedro | 1 |
| 2 | C語(yǔ)言入門 | 1 | pedro | 1 |
| 3 | JAVA高效編程 | 1 | pedro | 1 |
| 4 | JVM花落知多少 | 1 | pedro | 1 |
| 1 | SQL必知必會(huì) | 2 | peter | 1 |
| 2 | C語(yǔ)言入門 | 2 | peter | 1 |
| 3 | JAVA高效編程 | 2 | peter | 1 |
| 4 | JVM花落知多少 | 2 | peter | 1 |
| 1 | SQL必知必會(huì) | 3 | faker | 2 |
| 2 | C語(yǔ)言入門 | 3 | faker | 2 |
| 3 | JAVA高效編程 | 3 | faker | 2 |
| 4 | JVM花落知多少 | 3 | faker | 2 |
| 1 | SQL必知必會(huì) | 4 | lucy | 4 |
| 2 | C語(yǔ)言入門 | 4 | lucy | 4 |
| 3 | JAVA高效編程 | 4 | lucy | 4 |
| 4 | JVM花落知多少 | 4 | lucy | 4 |
| 1 | SQL必知必會(huì) | 5 | jery | <null> |
| 2 | C語(yǔ)言入門 | 5 | jery | <null> |
| 3 | JAVA高效編程 | 5 | jery | <null> |
| 4 | JVM花落知多少 | 5 | jery | <null> |
+----+---------------+----+----------+----------+
從結(jié)果中可以看出,交叉連接就是將一張表的每一條記錄與另一張表的每一條記錄進(jìn)行連接成為一條新記錄,排列組合完畢后得到兩張表的笛卡爾積。
交叉連接還可以通過(guò)隱式的連接方式來(lái)實(shí)現(xiàn):
SELECT * FROM imooc_class,imooc_user;
4. SQL Inner Join
內(nèi)連接(Inner Join),是將一張表的每一條記錄與另一張表的每一行記錄進(jìn)行比較,得到兩張表匹配的記錄集合。
維恩圖表示如下:
圖中深色部分便是最后的返回結(jié)果。
4.1 例2 內(nèi)連接
請(qǐng)書(shū)寫(xiě) SQL 語(yǔ)句,返回imooc_class
和imooc_user
兩表的內(nèi)連接集合。
分析:
使用 Select 搭配 Inner Join 即可。
語(yǔ)句
SELECT * FROM imooc_user INNER JOIN imooc_class ON imooc_user.class_id = imooc_class.id;
結(jié)果如下:
+----+----------+----------+----+---------------+
| id | username | class_id | id | class_name |
+----+----------+----------+----+---------------+
| 1 | pedro | 1 | 1 | SQL必知必會(huì) |
| 2 | peter | 1 | 1 | SQL必知必會(huì) |
| 3 | faker | 2 | 2 | C語(yǔ)言入門 |
| 4 | lucy | 4 | 4 | JVM花落知多少 |
+----+----------+----------+----+---------------+
一般情況下,交叉連接是默認(rèn)的連接方式,因此我們可以省略INNER
關(guān)鍵字:
SELECT * FROM imooc_user JOIN imooc_class ON imooc_user.class_id = imooc_class.id;
這樣也能得到同樣的結(jié)果;使用 Join 和 On 關(guān)鍵字可以顯式連接兩表,我們也可以通過(guò) Where 進(jìn)行隱式的連接:
SELECT * FROM imooc_user, imooc_class WHERE imooc_user.class_id = imooc_class.id;
5. 小結(jié)
- 交叉連接和內(nèi)連接真實(shí)的使用場(chǎng)景其實(shí)較少,不過(guò)使用也比較簡(jiǎn)單,多加操練記住即可。
- 本小節(jié)的例子中,imooc_user 與 imooc_class 的外鍵方式其實(shí)是不推薦的,真實(shí)業(yè)務(wù)中的外鍵方式將在后面的實(shí)戰(zhàn)部分介紹。