轉自 http://www.ruanyifeng.com/blog/2019/01/table-join.htmlhtml
關係型數據庫最難的地方,就是建模(model)。sql
錯綜複雜的數據,須要創建模型,才能儲存在數據庫。所謂"模型"就是兩樣東西:實體(entity)+ 關係(relationship)。數據庫
實體指的是那些實際的對象,帶有本身的屬性,能夠理解成一組相關屬性的容器。關係就是實體之間的聯繫,一般能夠分紅"一對一"、"一對多"和"多對多"等類型。3d
在關係型數據庫裏面,每一個實體有本身的一張表(table),全部屬性都是這張表的字段(field),表與表之間根據關聯字段"鏈接"(join)在一塊兒。因此,表的鏈接是關係型數據庫的核心問題。code
表的鏈接分紅好幾種類型。htm
- 內鏈接(inner join)
- 外鏈接(outer join)
- 左鏈接(left join)
- 右鏈接(right join)
- 全鏈接(full join)
之前,不少文章採用維恩圖(兩個圓的集合運算),解釋不一樣鏈接的差別。對象
上週,我讀到一篇文章,認爲還有比維恩圖更好的解釋方式。我發現確實如此,換一個角度解釋,更容易懂。blog
所謂"鏈接",就是兩張表根據關聯字段,組合成一個數據集。問題是,兩張表的關聯字段的值每每是不一致的,若是關聯字段不匹配,怎麼處理?好比,表 A 包含張三和李四,表 B 包含李四和王五,匹配的只有李四這一條記錄。ip
很容易看出,一共有四種處理方法。get
- 只返回兩張表匹配的記錄,這叫內鏈接(inner join)。
- 返回匹配的記錄,以及表 A 多餘的記錄,這叫左鏈接(left join)。
- 返回匹配的記錄,以及表 B 多餘的記錄,這叫右鏈接(right join)。
- 返回匹配的記錄,以及表 A 和表 B 各自的多餘記錄,這叫全鏈接(full join)。
下圖就是四種鏈接的圖示。我以爲,這張圖比維恩圖更易懂,也更準確。
上圖中,表 A 的記錄是 123,表 B 的記錄是 ABC,顏色表示匹配關係。返回結果中,若是另外一張表沒有匹配的記錄,則用 null 填充。
這四種鏈接,又能夠分紅兩大類:內鏈接(inner join)表示只包含匹配的記錄,外鏈接(outer join)表示還包含不匹配的記錄。因此,左鏈接、右鏈接、全鏈接都屬於外鏈接。
這四種鏈接的 SQL 語句以下。
SELECT * FROM A INNER JOIN B ON A.book_id=B.book_id; SELECT * FROM A LEFT JOIN B ON A.book_id=B.book_id; SELECT * FROM A RIGHT JOIN B ON A.book_id=B.book_id; SELECT * FROM A FULL JOIN B ON A.book_id=B.book_id;
上面的 SQL 語句還能夠加上where
條件從句,對記錄進行篩選,好比只返回表 A 裏面不匹配表 B 的記錄。
SELECT * FROM A LEFT JOIN B ON A.book_id=B.book_id WHERE B.id IS null;
另外一個例子,返回表 A 或表 B 全部不匹配的記錄。
SELECT * FROM A FULL JOIN B ON A.book_id=B.book_id WHERE A.id IS null OR B.id IS null;
此外,還存在一種特殊的鏈接,叫作"交叉鏈接"(cross join),指的是表 A 和表 B 不存在關聯字段,這時表 A(共有 n 條記錄)與表 B (共有 m 條記錄)鏈接後,會產生一張包含 n x m 條記錄的新表(見下圖)。