MySQL基本操作整理(四)、連接查詢

一、基本概念

1.含義

連接查詢又稱多表查詢,當要查詢的字段來自於多個表時,就會用到連接查詢。

2. 笛卡爾乘積現象

若表1有m行記錄,表2有n行記錄,當進行查詢時,會得到m*n行記錄

笛卡爾乘積使用的查詢語句如下: SELECT A.*, B.* FROM A, B;
即每一條A的記錄都對應B中的所有記錄,這樣共得到m*n條記錄

發生笛卡爾乘積現象的原因:沒有有效的連接條件
如何避免:添加有效的連接條件

3. 連接查詢的分類

  • 年代分類:
    sql92標準:僅僅支持內連接
    sql99標準【推薦】:支持內連接+外連接(左外和右外)+交叉連接
  • 功能分類:
    內連接:
      等值連接
      非等值連接
      自連接
    外連接:
      左外連接
      右外連接
      全外連接
    交叉連接

二、內連接

(一)sql92標準的內連接

1.等值連接

語法:SELECT 查詢列表 FROM 表1, 表2 WHERE 表1.key1 = 表2.key2;

① 多表等值連接的結果爲多表的交集部分
② n表連接,至少需要n-1個連接條件
③ 多表的順序沒有要求
④一般需要爲表起別名:提高語句的簡潔度,區分多個重名的字段
⑤可以搭配前面介紹的所有子句使用,比如排序、分組、篩選

案例1(等值連接簡單使用):查詢女神名和對應的男神名

SELECT NAME,boyName 
FROM boys,beauty
WHERE beauty.boyfriend_id = boys.id;

案例2(可以加篩選條件):查詢有獎金的員工名、部門名

SELECT last_name,department_name,commission_pct
FROM employees e,departments d
WHERE e.`department_id`= d.`department_id`
AND e.`commission_pct` IS NOT NULL;

案例3(可以加分組和排序):查詢每個工種的工種名和員工的個數,並且按員工個數降序

SELECT job_title, COUNT(*)
FROM employees e,jobs j
WHERE e.`job_id`= j.`job_id`
GROUP BY job_title
ORDER BY COUNT(*) DESC;

案例4(三表連接):查詢員工名、部門名和所在的城市,其中城市名以s開頭,並且按部門名降序

SELECT last_name,department_name,city
FROM employees e,departments d,locations l
WHERE e.`department_id`= d.`department_id`
AND d.`location_id`= l.`location_id`
AND city LIKE 's%'
ORDER BY department_name DESC;

2.非等值連接

語法:SELECT 查詢列表 FROM 表1, 表2 WHERE 表1.key1 BETWEEN 表2.key1 AND 表2.key2;

案例:查詢員工的工資和對應的工資級別

SELECT salary,grade_level
FROM employees e,job_grades g
WHERE salary BETWEEN g.`lowest_sal` AND g.`highest_sal`

3.自連接

自連接查詢的是同一個表中的某些字段,但需要對該表重命名爲兩個不同的表進行自連接查詢
語法:SELECT 查詢列表 FROM 表1 a, 表1 b WHERE a.key1 = b.key2;

案例:查詢員工名和上級的名稱

SELECT e.employee_id,e.last_name,m.employee_id,m.last_name
FROM employees e,employees m
WHERE e.`manager_id`= m.`employee_id`;

(二)sql99標準的內連接

  • 語法:
    SELECT 查詢列表 FROM 表1 別名 INNER JOIN 表2 別名 ON 連接條件 【where 篩選條件】 【group by 分組】 【having 篩選條件】【order by 排序列表】;
  • 特點:
    ① inner可以省略
    ② 可以添加排序、分組、篩選
    ③ 連接條件放在on後面,篩選條件放在where後面,提高分離性,便於閱讀
    ④ inner join連接和sql92語法中的等值連接效果是一樣的,都是查詢多表的交集

1. 等值連接

案例1(簡單使用):查詢員工名、部門名

SELECT last_name,department_name
FROM departments d
INNER JOIN  employees e
ON e.`department_id` = d.`department_id`;

案例2(添加分組+篩選+排序):查詢員工個數大於3的部門名和員工個數,並按個數降序

#查詢過程可以分兩步走:
#①查詢每個部門的員工個數
SELECT COUNT(*),department_name
FROM employees e
INNER JOIN departments d
ON e.`department_id`= d.`department_id`
GROUP BY department_name;

#②在①結果上篩選員工個數大於3的記錄,並排序
SELECT COUNT(*) 個數,department_name
FROM employees e
INNER JOIN departments d
ON e.`department_id`= d.`department_id`
GROUP BY department_name
HAVING COUNT(*)>3
ORDER BY COUNT(*) DESC;

案例3(三表查詢):查詢員工名、部門名、工種名,並按部門名降序

SELECT last_name,department_name,job_title
FROM employees e
INNER JOIN departments d ON e.`department_id`=d.`department_id`
INNER JOIN jobs j ON e.`job_id` = j.`job_id`
ORDER BY department_name DESC;

2. 非等值連接

案例1:查詢員工的工資級別

SELECT salary,grade_level
FROM employees e
JOIN job_grades g
ON e.`salary` BETWEEN g.`lowest_sal` AND g.`highest_sal`;

案例2:查詢每個工資級別的員工個數大於20的員工個數和工資級別,並且按工資級別降序

SELECT COUNT(*),grade_level
FROM employees e
JOIN job_grades g
ON e.`salary` BETWEEN g.`lowest_sal` AND g.`highest_sal`
GROUP BY grade_level
HAVING COUNT(*)>20
ORDER BY grade_level DESC;

3. 自連接

案例:查詢員工的名字、上級的名字

SELECT e.last_name,m.last_name
FROM employees e
JOIN employees m
ON e.`manager_id`= m.`employee_id`;

三、外連接

  • 應用場景:用於查詢一個表中有,另一個表沒有的記錄
  • 語法:
    SELECT 查詢列表 FROM 表1 別名 LEFT/RIFHT/FULL OUTER JOIN 表2 別名 ON 連接條件 【where 篩選條件】 【group by 分組】 【having 篩選條件】【order by 排序列表】;
  • 特點:
  1. 外連接的查詢結果爲主表中的所有記錄
    如果從表中有和它匹配的,則顯示匹配的值
    如果從表中沒有和它匹配的,則顯示null
    外連接查詢結果=內連接結果+主表中有而從表沒有的記錄
  2. 左外連接,left join 左邊的是主表
    右外連接,right join 右邊的是主表
  3. 左外和右外交換兩個表的順序,可以實現同樣的效果
  4. 全外連接=內連接的結果+表1中有但表2沒有的+表2中有但表1沒有的

1. 左外連接

案例1:查詢男朋友不在男神表的的女神名(即 beauty表中某些記錄的boyfriend_id沒有出現在boys表中的id中)

#分兩步走,先確定主表爲beauty,查詢兩表中的所有記錄,其中必然包含boyfriend_id在boys表中沒有相應的id的記錄
SELECT b.*,bo.* 
FROM beauty b 
LEFT OUTER JOIN boys bo 
ON b.`boyfriend_id` = bo.`id`;

#第二步,添加刪選條件,在查出的結果中選擇boys的id值爲null的記錄,得到結果
SELECT b.name 
FROM beauty b 
LEFT OUTER JOIN boys bo 
ON b.`boyfriend_id` = bo.`id`
WHERE bo.id IS NULL;

案例2:查詢哪個部門沒有員工

#先確定主表爲departments,查詢主表的所有部門名和對應的員工名
SELECT d.department_name,e.employee_id
FROM departments d
LEFT OUTER JOIN employees e
ON d.`department_id` = e.`department_id`

#查詢員工名爲null的部門名
SELECT d.department_name
FROM departments d
LEFT OUTER JOIN employees e
ON d.`department_id` = e.`department_id`
WHERE e.`employee_id` IS NULL;

2. 右外連接

右外連接和左外連接的唯一區別在於右外連接將主表放在了 RIGHT OUTER JOIN 的後面,從表放在FROM的後面,其他沒有區別。
因此以上的案例:查詢哪個部門沒有員工,用右外連接可以寫爲:

SELECT d.department_name
FROM employees e
RIGHT OUTER JOIN departments d
ON d.`department_id` = e.`department_id`
WHERE e.`employee_id` IS NULL;

3. 全外連接

MySQL不支持全外連接,但是可以簡單介紹一下全外連接的形式(Oracle等支持)

 SELECT b.*,bo.*
 FROM beauty b
 FULL OUTER JOIN boys bo
 ON b.`boyfriend_id` = bo.id;

以上語句執行後,可以查詢出 beauty表中 boyfriend_id在 boys表中的記錄,以及boyfriend_id不在boys表中的記錄(相應的boys表的字段顯示爲null),外加boys表中id在boyfriend_id中的記錄(相應的beauty表的字段顯示爲null)

4. 交叉連接

交叉連接顯示笛卡爾乘積結果

#該語句結果爲一個女神對應了n個男神,n爲boys表裏的記錄數
SELECT b.name, bo.boyName 
FROM beauty b 
CROSS JOIN boys bo;

四、連接查詢總結

1. sql92和sql99標準PK

  • 功能:sql99支持的較多,包括內連接、外連接、交叉連接
  • 可讀性:sql99實現連接條件和篩選條件的分離,可讀性較高

2.圖解連接查詢

1.內連接和外連接
在這裏插入圖片描述
2.添加查詢條件
在這裏插入圖片描述
3.全連接
在這裏插入圖片描述

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