1. 程式人生 > >連線查詢:JOIN

連線查詢:JOIN

定義:

連線查詢又稱為多表查詢,當查詢的欄位來源於多個表時,那麼就會用到多表查詢。

分類

按照年代分類
  1. sql92標準:在Mysql中只是支援內連線;
  2. sql99標準:在Mysql中支援了內連線、外連線(左外連線、右外連線)和交叉連線;也是推薦的一種寫法。
按照功能分類
  1. 內連線:等值連線、非等值連線、自連線;
  2. 外連線: 左外連線、右外連線、全外連線(mysql中不支援)
  3. 交叉連線。

資料準備

以下的sql語句均在MySQL資料庫中執行

mysql> select version();
+-----------+
| version() | +-----------+ | 5.7.22 | +-----------+ 1 row in set

1.部門表(tb_dept)

mysql> select * from tb_dept;
+----+-----------+
| id | dept_name |
+----+-----------+
|  1 | 開發部    |
|  2 | 測試部    |
|  3 | 銷售部    |
|  4 | HR部      |
|  5 | 服務部    |
+----+-----------+
5 rows in set

2.員工資訊表

mysql> select * from tb_emp;
+----+--------+---------+
| id | name   | dept_id |
+----+--------+---------+
|  1 | Mark   |       1 |
|  2 | Sammi  |       2 |
|  3 | Abel   |       2 |
|  4 | Dannel |       4 |
|  7 | Eason  |       3 |
|  8 | Sa     |       1 |
| 10 | other  |       0 |
+----+--------+---------+
7 rows in set

inner join

語法結構
select 查詢列表
from11別名
inner join22別名
on 連線條件
where 
group by
order by
limit

inner join(內連線)特點:

1.基於連線條件將兩張表的目標列組合取交集在一起,組成新的一張結果表;
2.inner 可以省略;
3.篩選條件放在where後面,連線條件方法放在on後面;
4.在表設計時連線條件的欄位的型別和長度最好保持一致。

demo:員工表和部門表進行內連線,連線條件為:員工表中的部門id等於部門表的id。

mysql> select * from tb_emp A inner join tb_dept B on A.dept_id=B.id;
+----+--------+---------+----+-----------+
| id | name   | dept_id | id | dept_name |
+----+--------+---------+----+-----------+
|  1 | Mark   |       1 |  1 | 開發部    |
|  2 | Sammi  |       2 |  2 | 測試部    |
|  3 | Abel   |       2 |  2 | 測試部    |
|  4 | Dannel |       4 |  4 | HR部      |
|  7 | Eason  |       3 |  3 | 銷售部    |
|  8 | Sa     |       1 |  1 | 開發部    |
+----+--------+---------+----+-----------+
6 rows in set

sql92寫法:

select * from tb_emp A, tb_dept B where A.dept_id=B.id;

left join

left join(左連線):顯示左表的全部記錄以及右表符合條件的記錄;如果右表中沒有匹配資料則顯示為null
1.員工表 左連線 部門表

mysql> select * from tb_emp A left join tb_dept B on A.dept_id=B.id;
+----+--------+---------+------+-----------+
| id | name   | dept_id | id   | dept_name |
+----+--------+---------+------+-----------+
|  1 | Mark   |       1 |    1 | 開發部    |
|  8 | Sa     |       1 |    1 | 開發部    |
|  2 | Sammi  |       2 |    2 | 測試部    |
|  3 | Abel   |       2 |    2 | 測試部    |
|  7 | Eason  |       3 |    3 | 銷售部    |
|  4 | Dannel |       4 |    4 | HR部      |
| 10 | other  |       0 | NULL | NULL      |
+----+--------+---------+------+-----------+
7 rows in set

2.部門表 左連線 員工表

mysql> select * from tb_dept A left join tb_emp B on A.id=B.dept_id;
+----+-----------+------+--------+---------+
| id | dept_name | id   | name   | dept_id |
+----+-----------+------+--------+---------+
|  1 | 開發部    |    1 | Mark   |       1 |
|  2 | 測試部    |    2 | Sammi  |       2 |
|  2 | 測試部    |    3 | Abel   |       2 |
|  4 | HR部      |    4 | Dannel |       4 |
|  3 | 銷售部    |    7 | Eason  |       3 |
|  1 | 開發部    |    8 | Sa     |       1 |
|  5 | 服務部    | NULL | NULL   | NULL    |
+----+-----------+------+--------+---------+
7 rows in set

right join

right join(右連線):顯示右表的全部記錄以及左表符合條件的記錄;如果左表中沒有匹配資料則顯示為null
1.部門表 右連線 員工表 (查詢的結果和 員工表 左連線 部門表 是一樣的)

mysql> select * from tb_dept A right join tb_emp B on A.id=B.dept_id;
+------+-----------+----+--------+---------+
| id   | dept_name | id | name   | dept_id |
+------+-----------+----+--------+---------+
|    1 | 開發部    |  1 | Mark   |       1 |
|    1 | 開發部    |  8 | Sa     |       1 |
|    2 | 測試部    |  2 | Sammi  |       2 |
|    2 | 測試部    |  3 | Abel   |       2 |
|    3 | 銷售部    |  7 | Eason  |       3 |
|    4 | HR部      |  4 | Dannel |       4 |
| NULL | NULL      | 10 | other  |       0 |
+------+-----------+----+--------+---------+
7 rows in set

2.員工表 右連線 部門表 (查詢的結果和 部門表 左連線 員工表 是等介的)

mysql> select * from tb_emp A right join tb_dept B on A.dept_Id=B.id;
+------+--------+---------+----+-----------+
| id   | name   | dept_id | id | dept_name |
+------+--------+---------+----+-----------+
|    1 | Mark   |       1 |  1 | 開發部    |
|    2 | Sammi  |       2 |  2 | 測試部    |
|    3 | Abel   |       2 |  2 | 測試部    |
|    4 | Dannel |       4 |  4 | HR部      |
|    7 | Eason  |       3 |  3 | 銷售部    |
|    8 | Sa     |       1 |  1 | 開發部    |
| NULL | NULL   | NULL    |  5 | 服務部    |
+------+--------+---------+----+-----------+
7 rows in set

cross join

cross join:交叉連線或者又稱為 笛卡爾連線或者叉乘連線。在cross join 中可以不使用on。如果進行連線操作的表記錄過多的話,那麼儘可能避免使用cross join。
1.部門表和與員工表進行交叉連線

mysql> select * from tb_emp A cross join tb_dept B ;
+----+--------+---------+----+-----------+
| id | name   | dept_id | id | dept_name |
+----+--------+---------+----+-----------+
|  1 | Mark   |       1 |  1 | 開發部    |
|  1 | Mark   |       1 |  2 | 測試部    |
|  1 | Mark   |       1 |  3 | 銷售部    |
|  1 | Mark   |       1 |  4 | HR部      |
|  1 | Mark   |       1 |  5 | 服務部    |
|  2 | Sammi  |       2 |  1 | 開發部    |
|  2 | Sammi  |       2 |  2 | 測試部    |
|  2 | Sammi  |       2 |  3 | 銷售部    |
|  2 | Sammi  |       2 |  4 | HR部      |
|  2 | Sammi  |       2 |  5 | 服務部    |
|  3 | Abel   |       2 |  1 | 開發部    |
|  3 | Abel   |       2 |  2 | 測試部    |
|  3 | Abel   |       2 |  3 | 銷售部    |
|  3 | Abel   |       2 |  4 | HR部      |
|  3 | Abel   |       2 |  5 | 服務部    |
|  4 | Dannel |       4 |  1 | 開發部    |
|  4 | Dannel |       4 |  2 | 測試部    |
|  4 | Dannel |       4 |  3 | 銷售部    |
|  4 | Dannel |       4 |  4 | HR部      |
|  4 | Dannel |       4 |  5 | 服務部    |
|  7 | Eason  |       3 |  1 | 開發部    |
|  7 | Eason  |       3 |  2 | 測試部    |
|  7 | Eason  |       3 |  3 | 銷售部    |
|  7 | Eason  |       3 |  4 | HR部      |
|  7 | Eason  |       3 |  5 | 服務部    |
|  8 | Sa     |       1 |  1 | 開發部    |
|  8 | Sa     |       1 |  2 | 測試部    |
|  8 | Sa     |       1 |  3 | 銷售部    |
|  8 | Sa     |       1 |  4 | HR部      |
|  8 | Sa     |       1 |  5 | 服務部    |
| 10 | other  |       0 |  1 | 開發部    |
| 10 | other  |       0 |  2 | 測試部    |
| 10 | other  |       0 |  3 | 銷售部    |
| 10 | other  |       0 |  4 | HR部      |
| 10 | other  |       0 |  5 | 服務部    |
+----+--------+---------+----+-----------+
35 rows in set

結果集的記錄數=員工表(7條記錄)*部門表(5表記錄)=35條記錄;該現象稱為笛卡爾積現象。
該查詢結果和下面的sql結果是相等的。都為逐步取出員工表的每一行記錄去和部門表的每一條記錄進行組合。

 select * from tb_emp , tb_dept  ;