文章目錄
一、基本概念
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 排序列表】;
- 特點:
- 外連接的查詢結果爲主表中的所有記錄
如果從表中有和它匹配的,則顯示匹配的值
如果從表中沒有和它匹配的,則顯示null
外連接查詢結果=內連接結果+主表中有而從表沒有的記錄 - 左外連接,left join 左邊的是主表
右外連接,right join 右邊的是主表 - 左外和右外交換兩個表的順序,可以實現同樣的效果
- 全外連接=內連接的結果+表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.全連接