MySQL多表查詢之橫向連接

我們之前學習的SELECT語句都是單表查詢,隨着我們使用數據庫的靈活性越來越高,當我們需要的數據在不同的表中時,就需要使用多表查詢來檢索我們需要的數據。
多表查詢分爲橫向連接查詢和縱向合併查詢。
連接查詢是通過多張表中共有的關鍵字段,將多張表連成一張虛擬結果集,來補充字段信息,我們可以按照業務需求檢索多張表中的數據。

SQL查詢的基本原理:

  • 單表查詢:根據where條件過濾表中的記錄,然後根據select指定的列返回查詢結果。
  • 兩表連接查詢:使用on條件對兩表進行連接形成一張虛擬結果集;然後根據where條件過濾結果集中的記錄,再根據select指定的列返回查詢結果。
  • 多表連接查詢:先對第一個和第二個表按照兩表連接查詢,然後用用連接後的虛擬結果集和第三個表做連接查詢,以此類推,直到所有的表都連接上爲止,最終形成一張虛擬結果集,然後根據where條件過濾虛擬結果集中的記錄,再根據select指定的列返回查詢結果。

多表連接的結果通過三個屬性決定:

  • 方向性:在外連接中寫在前邊的表爲左表、寫在後邊的表爲右表。
  • 主附關係:主表要出所有的數據範圍,附表與主表無匹配項時標記爲null,內連接時無主附表之分。
  • 對應關係:關鍵字段中有重複值的表爲多表,沒有重複值的表爲一表。

對應關係:

  • 一對一
    在這裏插入圖片描述
  • 一對多或多對一
    在這裏插入圖片描述
  • 多對多
    在這裏插入圖片描述

MySQL支持的連接方式:內連接和外連接(左外連接、右外連接)。

  • 內連接:按照連接條件,返回兩張表中滿足條件的記錄。
    在這裏插入圖片描述
select <字段名1>[,<字段名2>...,<字段名n>] from <表名1>[ inner] join <表名2> on <連接條件>

等值連接:連接條件是兩張表中的關鍵字段取值相等。

mysql> select ename,job,hiredate,sal,dname
    -> from emp
    -> inner join dept
    -> on emp.deptno=dept.deptno;
+--------+-----------+------------+------+------------+
| ename  | job       | hiredate   | sal  | dname      |
+--------+-----------+------------+------+------------+
| clark  | manager   | 1981-06-09 | 2450 | accounting |
| king   | persident | 1981-11-17 | 5000 | accounting |
| miller | clerk     | 1982-01-23 | 1300 | accounting |
| smith  | clerk     | 1980-12-17 |  800 | research   |
| jones  | manager   | 1981-04-02 | 2975 | research   |
| scott  | analyst   | 1987-04-19 | 3000 | research   |
| adams  | clerk     | 1987-05-23 | 1100 | research   |
| ford   | analyst   | 1981-12-03 | 3000 | research   |
| allen  | salesman  | 1981-02-20 | 1600 | sales      |
| ward   | salesman  | 1981-02-22 | 1250 | sales      |
| martin | salesman  | 1981-09-28 | 1250 | sales      |
| blake  | manager   | 1981-05-01 | 2850 | sales      |
| turner | salesman  | 1981-09-08 | 1500 | sales      |
| james  | clerk     | 1981-12-03 |  950 | sales      |
+--------+-----------+------------+------+------------+

不等值連接:連接條件是兩張表中的關鍵字段取值滿足非等值比較運算。

mysql> select ename,job,hiredate,sal,grade
    -> from emp
    -> inner join salgrade
    -> on sal between losal and hisal;
+--------+-----------+------------+------+-------+
| ename  | job       | hiredate   | sal  | grade |
+--------+-----------+------------+------+-------+
| smith  | clerk     | 1980-12-17 |  800 |     1 |
| allen  | salesman  | 1981-02-20 | 1600 |     3 |
| ward   | salesman  | 1981-02-22 | 1250 |     2 |
| jones  | manager   | 1981-04-02 | 2975 |     4 |
| martin | salesman  | 1981-09-28 | 1250 |     2 |
| blake  | manager   | 1981-05-01 | 2850 |     4 |
| clark  | manager   | 1981-06-09 | 2450 |     4 |
| scott  | analyst   | 1987-04-19 | 3000 |     4 |
| king   | persident | 1981-11-17 | 5000 |     5 |
| turner | salesman  | 1981-09-08 | 1500 |     3 |
| adams  | clerk     | 1987-05-23 | 1100 |     1 |
| james  | clerk     | 1981-12-03 |  950 |     1 |
| ford   | analyst   | 1981-12-03 | 3000 |     4 |
| miller | clerk     | 1982-01-23 | 1300 |     2 |
+--------+-----------+------------+------+-------+

笛卡爾積連接:兩張表中的每一條記錄進行笛卡爾積組合,然後根據where條件過濾虛擬結果集中的記錄。

select <字段名1>[,<字段名2>...,<字段名n>] from <表名1>,<表名2> where <篩選條件>
mysql> select ename,job,hiredate,sal,dname
    -> from emp,dept
    -> where emp.deptno=dept.deptno;
+--------+-----------+------------+------+------------+
| ename  | job       | hiredate   | sal  | dname      |
+--------+-----------+------------+------+------------+
| clark  | manager   | 1981-06-09 | 2450 | accounting |
| king   | persident | 1981-11-17 | 5000 | accounting |
| miller | clerk     | 1982-01-23 | 1300 | accounting |
| smith  | clerk     | 1980-12-17 |  800 | research   |
| jones  | manager   | 1981-04-02 | 2975 | research   |
| scott  | analyst   | 1987-04-19 | 3000 | research   |
| adams  | clerk     | 1987-05-23 | 1100 | research   |
| ford   | analyst   | 1981-12-03 | 3000 | research   |
| allen  | salesman  | 1981-02-20 | 1600 | sales      |
| ward   | salesman  | 1981-02-22 | 1250 | sales      |
| martin | salesman  | 1981-09-28 | 1250 | sales      |
| blake  | manager   | 1981-05-01 | 2850 | sales      |
| turner | salesman  | 1981-09-08 | 1500 | sales      |
| james  | clerk     | 1981-12-03 |  950 | sales      |
+--------+-----------+------------+------+------------+

自連接:通過設置表別名,將一張表虛擬成多張表。

mysql> select t1.ename as 員工姓名,t2.ename as 領導姓名
    -> from emp as t1
    -> inner join emp as t2
    -> on t1.mgr=t2.empid;
+----------+----------+
| 員工姓名 | 領導姓名 |
+----------+----------+
| smith    | ford     |
| allen    | blake    |
| ward     | blake    |
| jones    | king     |
| martin   | blake    |
| blake    | king     |
| clark    | king     |
| scott    | jones    |
| turner   | blake    |
| adams    | scott    |
| james    | blake    |
| ford     | jones    |
| miller   | clark    |
+----------+----------+

表限定符.:如果表1和表2中的字段名相同,則必須使用表限定符.指定引用的是哪個表中的字段。

  • 左連接:按照連接條件,返回兩張表中滿足條件的記錄,以及左表中的所有記錄,右表匹配不到顯示爲null。
    在這裏插入圖片描述
select <字段名1>[,<字段名2>...,<字段名n>] from <表名1> left join <表名2> on <連接條件>

示例:查詢每個部門的員工數(沒有員工的部門,員工數統計爲0)

mysql> select dept.deptno,dname,count(empid)
    -> from dept
    -> left join emp
    -> on dept.deptno=emp.deptno
    -> group by dept.deptno;
+--------+------------+--------------+
| deptno | dname      | count(empid) |
+--------+------------+--------------+
|     10 | accounting |            3 |
|     20 | research   |            5 |
|     30 | sales      |            6 |
|     40 | operations |            0 |
+--------+------------+--------------+
  • 右連接:按照連接條件,返回兩張表中滿足條件的記錄,以及右表中的所有記錄,左表匹配不到顯示爲null。
    在這裏插入圖片描述
select <字段名1>[,<字段名2>...,<字段名n>] from <表名1> right join <表名2> on <連接條件>

示例:查詢每個部門的員工數(沒有員工的部門,員工數統計爲0)

mysql> select dept.deptno,dname,count(empid)
    -> from emp
    -> right join dept
    -> on dept.deptno=emp.deptno
    -> group by dept.deptno;
+--------+------------+--------------+
| deptno | dname      | count(empid) |
+--------+------------+--------------+
|     10 | accounting |            3 |
|     20 | research   |            5 |
|     30 | sales      |            6 |
|     40 | operations |            0 |
+--------+------------+--------------+

多表連接規則

  • 確定查詢的信息在哪幾張表
  • 確定表和表之間的對應關係和主附關係
  • 確定表和表之間的連接條件

一表作爲主表可以保證維度的完整性,多表作爲主表可以保證度量的準確性。在沒有明確表示需要保證維度完整性的情況下,優先保證度量的準確性,所以將度量值所在的表作爲主表。度量字段通常存在於多表中,因此通常情況下可以將多表作爲主表進行外連接。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章