一步一步學MySQL----13 多表資料記錄查詢之內連線
前面學的查詢都是單表查詢,而在實際應用中,經常需要實現在一個查詢語句中顯示多張表的資料,這就是所謂的多表資料記錄查詢,簡稱連線查詢。
12.1 關係資料操作
(1)並(UNION)
“並”就是把具有相同欄位數目和欄位型別的表合併到一起。(2)笛卡兒積(CARTESIAN PRODUCT)
笛卡兒積就是沒有連線條件表關係返回的結果。(3)內連線(INNER JOIN)
在表關係的笛卡兒積資料記錄中,保留表關係中所有匹配的資料記錄,捨棄不匹配的資料記錄。
內連線主要有以下三種連線方式:
自然連線:首先根據表關係中相同名稱的欄位自動進行記錄匹配,然後去掉重複的欄位。
等值連線:等值連線操作就是表關係的笛卡兒積中,選擇所匹配欄位值相等的資料記錄。等值連線關係資料操作需要在執行過程中的用“符號=”指定匹配條件,在新關係中不會去掉重複欄位。
不等連線:笛卡爾積中,選擇所匹配欄位值不相等(!=)的資料記錄。與自然連線相比,不等連線關係資料操作需要在執行過程中用符號!=指定匹配條件,在新關係中不會去掉重複欄位。
(4)外連線(OUTER JOIN)
左外連線:就是表關係的笛卡兒積中,除了選擇相匹配的資料記錄,還包含關聯左邊表中不匹配的資料記錄
右外連線:就是表關係的笛卡兒積中,除了選擇相匹配的資料記錄,還包含關聯右邊表中不匹配的資料記錄
全外連線:就是表關係的笛卡兒積中,除了選擇相匹配的資料記錄,還包含關聯左右兩邊表中不匹配的資料記錄
下面的例項基於資料庫company,有如下兩張表:
(1) 部門表:department
(2) 員工表:employee
12.2 內連線之自然連線
所謂自然連線,就是指表與其自身進行連線。
例如:執行SQL語句“inner join…on”,在資料庫company中,查詢每個員工的姓名、工種、領導姓名。
【例項分析】
(1) 確定需要查詢的表和所查詢欄位的來源
根據需求,我們需要查詢兩張表:員工表(employee)和領導表(employee),前者需要查詢出員工的姓名和工種,後者需要查詢出領導的姓名。
注意:由於表employee綜合了員工和領導的資訊,所以employee既是員工表也是領導表
(2) 確定關聯匹配條件
Employee.mgno(員工表的領導編號)=employee.empno(領導表的領導編號)
【實現步驟】
第一步:查詢每一位員工的姓名和工種
mysql> select e.ename employeename,e.job from employee e;
第二步:引入領導表,同時新增一條消除笛卡爾積的匹配條件
mysql> select e.ename employeename,e.job job,l.ename loadername from employee e inner join employee l on e.mgno=l.empno;
上面的語句也可以改寫成select from where的形式,如下:
mysql> select e.ename employeename,e.job job,l.ename loadername from employee e, employee l where e.mgno=l.empno;
特別說明:當表的名稱特別長時,直接使用表名很不方便,或者在實現表自然連線的時候,直接使用表名沒有辦法區分表。為了解決這些問題,MySQL提供了一種為表取別名的機制,具體語法如下:
select field1,field2,…fieldn [as] otherfieldn from table_name1 [as] other_table_name1,…,table_namen [as] other_table_namen
注意:在上述語句中table_name為原表名,other_table_name為新表名,其中的[as]可寫可不寫。
12.3 內連線之等值連線
所謂等值連線,就是在關鍵字ON後的匹配條件中通過等於關係運算符(=)來實現等值條件。
例如1:執行SQL語句“inner join on”,在資料庫company中,查詢每個員工的工號、姓名、工種、部門名稱、位置。
【例項分析】
(1) 確定需要查詢的表和所查詢欄位的來源
根據要求需要查詢兩張表:部門表和員工表,前者需要查詢出部門的名稱和位置,後者需要查詢出員工的工號、姓名和工種。
(2) 確定關聯匹配條件
department.depno=employee.depno
【實現步驟】
第一步:查詢每一位員工的工號、姓名和工種。
mysql> select e.empno,e.ename,e.job from employee e;
第二步:為查詢中引入部門表,同時新增一條消除笛卡爾積的匹配條件
mysql> select e.empno,e.ename,e.job,d.dname,d.location from employee e inner join department d on d.depno=e.depno;
上面的語句也可以改寫成select from where的形式,如下:
mysql> select e.empno,e.ename,e.job,d.dname,d.location from employee e,department d where d.depno=e.depno;
例如2:執行SQL語句“inner join on”,在資料庫company中,查詢每個員工的工號、姓名、薪水、工種、領導的姓名、部門名稱、位置。
【例項分析】
(1) 確定需要查詢的表和所查詢欄位的來源
根據需求需要查詢三張表:部門表(department)、員工表(employee)、領導表(employee),分別查詢如下欄位:
- 員工表:員工的工號、姓名、薪水和工種
- 領導表:領導的姓名
- 部門表:部門名稱和位置
(2) 確定關聯匹配條件
領導表連線部門表匹配條件:employee.depno=department.depno
員工表連線領導表匹配條件:employee.mgno=employee.empno
【實現步驟】
第一步:查詢每一位員工的工號、姓名、薪水和工種。
mysql> select e.empno,e.ename employeename,e.salary,e.job from employee e;
第二步:引入領導表,同時新增一條消除笛卡爾積的匹配條件
mysql> select e.empno,e.ename employeename,e.salary,e.job,l.ename loadername from employee e inner join employee l on e.mgno=l.empno;
第三步:引入部門表,同時新增一條消除笛卡爾積的匹配條件
mysql> select e.empno,e.ename employeename,e.salary,e.job,l.ename loadername,d.dname,d.location from employee e inner join employee l on e.mgno=l.empno inner join department d on l.depno=d.depno;
上面的語句也可以改寫成select from where的形式,如下:
mysql> select e.empno,e.ename employeename,e.salary,e.job,l.ename loadername,d.dname,d.location from employee e, employee l, department d where e.mgno=l.empno and l.depno=d.depno;
12.4 內連線之不等連線
所謂不等連線,就是在關鍵字ON後的匹配條件中通過除了等於關係運算符來實現不等條件外,可以使用的關係運算符包含“>”,“>=”,“<”,“<=”和“!=”。
例如:執行SQL語句“inner join on”,在資料庫company中,查詢員工工號大於其領導工號的每個員工的姓名、工種、領導姓名。
【例項分析】
(1) 確定需要查詢的表和所查詢欄位的來源
根據要求需要查詢兩張表:員工表和領導表(都是employee),前者需要查詢出員工的姓名和工種,後者需要查詢出其領導的姓名。
(2) 確定關聯匹配條件
employee.mgno(員工表的領導工號)=employee.empno(領導表的領導工號);
employee.empno(員工表的員工工號)>employee.empno(領導表的領導工號)
【實現步驟】
第一步:查詢每一位員工的姓名和工種
mysql> select e.ename employeename,e.job from employee e;
第二步:引入領導表,同時新增一條消除笛卡爾積的匹配條件
mysql> select e.ename employeename,e.job,l.ename loadername from employee e inner join employee l on e.mgno=l.empno and e.empno>l.empno;
上面的語句也可以改寫成select from where的形式,如下:
mysql> select e.ename employeename,e.job,l.ename loadername from employee e, employee l where e.mgno=l.empno and e.empno>l.empno;