前言
本文還是秉持之前一貫的寫作風格,以簡單易懂的示例幫助大家了解各種join的區別。
為什麼需要join
為什麼需要join?join中文意思為連接,連接意味著關聯即將一個表和多個表之間關聯起來。在處理資料庫表的時候,我們經常會發現,需要從多個表中獲取信息,將多個表的多個字段數據組裝起來再返回給調用者。所以join的前提是這些表格之間必須有關聯欄位。
join的分類
join分為兩種,inner join和outer join,其中outer join分為三種,left outer join, right outer join, full outer in,left outer join, right outer join, full outer in,left outer join, right outer join, full outer in in,left即大家所熟知的左連結。
join分為兩種,inner join和outer join,其中outer join分為三種,left outer join, right outer join, full outer join,另外left outer join又簡稱為大家所熟知的左連接。
各種join的區別
在介紹各種join的區別之前,我們先來看一個簡單的範例:
場景描述:
網路時代,大家都喜歡在網路上購物,尤其是淘寶和東京時代,大家都喜歡在網路上購物,尤其是淘寶和東京人所以我們選擇的場景也是大家熟悉的網路購物。這是一個關於一個人和他在商城買了什麼商品的一個故事;
針對上述需求,我們建立了兩張表,tb_person和tb_order,其中tb_person是關於這個人的描述,tb_order是關於他購買的商品的一個描述。
我們的表結構很簡單,tb_person只需要知道這個人是誰就可以了,所以只有三個字段id,firstname(名)和lastname(姓),同樣tb_order也很簡單,我們只要知道誰買了什麼商品,所以只需要3個字段,分別是oid, oname(商品名稱), pid(購買者編號)。
tb_person:
+-----------+-------------+------+-----+---- -----+----------------+
| Field | Type | Null | Key | Default | --+-------------+------+-----+---------+---------- ------+
| pid | int(11) | NO | PRI | NULL |Nau_increment | | NULL | |
| lastname | |
| lastname | varchar(50) | YES | | NULL | |
-+----------+-------------------+----------------+----------- --------+----------------+
tb_order:
+-------+--------- ----+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----+-------------+------+----+--+------+----+--+------+----+--+------+---- -------+----------------+
| oid | int(11) | NO | PRI | NULL | auto_increment NULL | |
| pid | |
+-------+-------------+------+-----+---------+--- -------------+
接下來,我們在上述兩張表中寫入一些範例資料:
data in tb_person:
+-----+----- ------+----------+
| pid | firstname | lastname |
+-----+-----------+-- --------+
| 1 | andy | chen |
| | abby | sun |
+-----+----- ------+----------+
tb_person表中有三位人員,分別是andy Chen, irri Wan, abby Sun;
data in tb_order:
+--- --+----------+------+
| oid | oname | pid |
+-----+----------+ ------+
| 1 | book | 1 |
| 2 | phone 4 |
+-----+------- ---+------+
tb_order表中記錄了3筆數據,人員編號為1也就是andy Chen買了兩件商品分別是book和phone,另外還有一個人員編號為4的人買了一件商品computer。關於這個大家可能會產生疑問,為什麼tb_person表中沒有人員編號為4的人呢?這裡我們姑且認為由於註冊用戶較多,我們採用了用戶分錶策略,所以人員編號為4的用戶可能在另外一張人員表中。
從之前的描述我們知道,表與表之間如果要join則必須要有關聯的字段,上述示例我們看到這個關聯的字段就是pid。
根據tb_person和tb_order兩張表,我們可以看到有三種情形:
person表中的人購買了商品,也就是order表中有關於該用戶的商品購買記錄,我們可以從該表中查詢到該用戶買了哪些商品,如andy Chen購買了book和phone兩種商品,即pid在tb_person和tb_order兩種表中都存在;
person表中的人未購買商品,如irri Wan和abby Sun兩位使用者並未購買任何商品,即pid只存在於tb_person表;
order表中購買商品的用戶在person表中找不到記錄,如pid為4的用戶購買了一台computer但在tb_person表中沒有該使用者的記錄,即pid只存在於tb_order表;
理解上述三種情形對於我們理解join有非常大的幫助,接下來我們將具體的分析每種join的區別:
INNER JOIN
所謂inner join的意思就是我們前面提到的情形1,pid必須在tb_person和tb_order兩張表中同時存在;
MariaDB [demo]> SELECT p.pid, p.firstname, o.oname -> FROM tb_person p -> INNER JOIN tb_order o -> ON p.pid=o.pid;
+-----+-----------+-- -----+
| pid | firstname | oname |
+-----+-----------+-------+
| 1 | andy | book |
| 1 | andy | phone |
+-----+-----------+-------+
〜LEFT tb_order的意思是上述情形1,情形2的並集。 LEFT JOIN的結果集不僅包含INNER JOIN的結果,還包含所有tb_person中沒有購買任何商品的使用者集。MariaDB [demo]> SELECT p.pid, p.firstname, o.oname -> FROM tb_person p -> LEFT JOIN tb_order o -> ON p.pid=o.pid;+-----+-----------+-------+| pid | firstname | oname |+-----+-- ---------+-------+| 1 | andy | book |
| 1 | andy | phone |
| 2 | irri | NULL |
| 3 | abby | NULL |
+-----+-----------+-------+
RIGHT JOIN
tb_person RIGHT JOIN tb_order的意思是上述情形1和情形3的并集。RIGHT JOIN的结果集不仅包含INNER JOIN的结果,而且还包含所有tb_order中所有已经购买商品的用户但该用户记录不存在于tb_person表。
MariaDB [demo]> SELECT p.pid, p.firstname, o.oname -> FROM tb_person p -> RIGHT JOIN tb_order o -> ON p.pid=o.pid;
+------+-----------+----------+
| pid | firstname | oname |
+------+-----------+----------+
| 1 | andy | book |
| 1 | andy | phone |
| NULL | NULL | computer |
+------+-----------+----------+
FULL JOIN
故名思议,FULL JOIN就是上述情形1,2,3的并集了,但是mysql数据库不支持full join查询,所以我们只能LEFT JOIN union RIGHT JOIN,才能得到FULL JOIN的结果。
MariaDB [demo]> SELECT p.pid, p.firstname, o.oname -> FROM tb_person p -> LEFT JOIN tb_order o -> ON p.pid=o.pid -> UNION -> SELECT p.pid, p.firstname, o.oname -> FROM tb_person p -> RIGHT JOIN tb_order o -> ON p.pid=o.pid;
+------+-----------+----------+
| pid | firstname | oname |
+------+-----------+----------+
| 1 | andy | book |
| 1 | andy | phone |
| 2 | irri | NULL |
| 3 | abby | NULL |
| NULL | NULL | computer |
+------+-----------+----------+
注:我们上述的sql语句全部基于mysql数据库执行。
总结
本文主要描述了sql join的分类以及各种join的区别,通过简单的示例,让大家更清晰的去了解他们。至于什么时候使用join要视具体的情况而定,根据不同的需求采用不同的策略。
非常感谢大家的热心回复,可能有些问题的探讨超出了本文的范畴,但是非常乐意大家提出问题,然后大家一起去探索去发现。
引用
NULL
附件
demo.sql文件
create database demo; use demo; create table tb_person ( pid int(11) auto_increment, firstname varchar(50), lastname varchar(50), primary key(pid) ); create table tb_order ( oid int(11) auto_increment, oname varchar(50), pid int(11), primary key(oid) ); insert into tb_person(firstname, lastname) values('andy','chen'); insert into tb_person(firstname, lastname) values('irri','wan'); insert into tb_person(firstname, lastname) values('abby','sun'); insert into tb_order(oname, pid) values('book', 1); insert into tb_order(oname, pid) values('phone', 1); insert into tb_order(oname, pid) values('computer', 4);