參考連結
- https://www.bilibili.com/video/BV12b411K7Zu?p=69
連接配接查詢
含義
連接配接查詢,又稱多表查詢,當查詢的字段來自于多個表時,就會用到連接配接查詢
笛卡爾乘積現象
如果表1有m行,表2有n行,結果=m*n行。發生原因是沒有有效的連接配接條件。
分類
按年代分類
- sql92标準:僅僅支援内連接配接
- sql99标準【推薦】:支援内連接配接+外連接配接(左外和右外)+交叉連接配接
按功能分類
内連接配接
- 等值連接配接
- 非等值連接配接
- 自連接配接
外連接配接
- 左外連接配接
- 右外連接配接
- 全外連接配接
交叉連接配接
sql92标準
等值連接配接
- 多表等值連接配接的結果為多表的交集部分
- n表連接配接,至少需要n-1個連接配接條件
- 多表的順序沒有要求
- 一般需要為表起别名
簡單查詢
比如,“查詢員工名和對應的部門名”
SELECT
last_name,
department_name
FROM
employees,
departments
WHERE
employees.department_id = departments.department_id;
為表起别名
為表起别名,提高簡潔度。如果為表起了别名,則查詢的字段就不能使用原來的表名
比如,“查詢員工名、工種号、工種名”
SELECT
last_name,
e.job_id,
job_title
FROM
employees e,
jobs j
WHERE
e.job_id=j.job_id;
添加篩選條件
比如,“查詢有獎金的員工名、部門名”
SELECT
last_name,
department_name
FROM
employees e,
departments d
WHERE
e.department_id=d.department_id
AND
e.commission_pct IS NOT NULL;
又如,“查詢城市名中第二個字元為o的部門名和城市名”
SELECT
department_name,
city
FROM
departments d,
locations l
WHERE
d.location_id=l.location_id
AND
city LIKE '_o%';
添加分組
比如,“查詢每個城市的部門個數”
SELECT
COUNT(*) 個數,
city
FROM
departments d,
locations l
WHERE
d.location_id=l.location_id
GROUP BY
city;
又如,“查詢有獎金的每個部門的部門名和部門的上司編号和該部門的最低工資”
SELECT
department_name,
d.manager_id,
MIN(salary)
FROM
departments d,
employees e
WHERE
d.department_id=e.department_id
AND
commission_pct IS NOT NULL
GROUP BY
department_name, d.manager_id;
添加排序
比如,“查詢每個工種的工種名和員工的個數,并且按員工個數降序”
SELECT
job_title,
COUNT(*)
FROM
employees e,
jobs j
WHERE
e.job_id=j.job_id
GROUP BY
job_title
ORDER BY
COUNT(*) DESC;
三表連接配接
比如,“查詢員工名、部門名和所在的城市”
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;
非等值連接配接
比如,“查詢員工的工資和工資級别”
SELECT
salary,
grade_level
FROM
employees e,
job_grades g
WHERE
salary BETWEEN g.lowest_sal AND g.highest_sal
自連接配接
比如,“查詢員工名和上級的名稱”
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 别名【連接配接類型】
JOIN
表2 别名
ON
連接配接條件
WHERE
篩選條件
GROUP BY
分組
HAVING
篩選條件
ORDER BY
排序清單
分類
- 内連接配接:inner
- 外連接配接:a)左外:left【outer】;2)右外:right【outer】;全外:full【outer】
- 交叉連接配接
内連接配接
文法
SELECT
查詢清單
FROM
表1 别名
INNER JOIN
表2 别名
ON
連接配接條件;
分類
- 等值
- 非等值
- 自連接配接
特點
- INNER可以省略
- 篩選條件放在WHERE後面,連接配接條件放在ON後面,提高分離性,便于閱讀
等值連接配接
簡單使用
比如,“查詢員工名、部門名”
SELECT
last_name,
department_name
FROM
employees e
INNER JOIN
departments d
ON
e.department_id=d.department_id;
添加篩選
比如,“查詢名字中包含e的員工名和工種名”
SELECT
last_name,
job_title,
FROM
employees e
INNER JOIN
jobs j
ON
e.job_id=j.job_id
WHERE
last_name LIKE "%e%";
添加分組+篩選
比如,“查詢部門個數>3的城市名和部門個數”
SELECT
city,
COUNT(*)
FROM
locations l
INNER JOIN
departments d
ON
d.location_id=l.location_id
GROUP BY
city
HAVING
COUNT(*)>3;
添加排序
比如,“查詢哪個部門的員工個數>3的部門名和員工個數,并按個數降序”
SELECT
department_name,
COUNT(*)
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;
三表連接配接
比如,“查詢員工名、部門名、工種名,并按部門名降序”
SELECT
last_name,
department_name,
job_title
FROM
employees e
INNER JOIN
department d ON e.department_id=d.department_id
INNER JOIN
jobs j ON e.job_id=j.job_id
ORDER BY
department_name DESC;
非等值連接配接
比如,“查詢員工的工資級别”
SELECT
salary,
grade_level
FROM
employees e
JOIN
job_grades g
ON
e.salary BETWEEN g.lowest_sal AND g.highest_sal;
又如,“查詢工資級别的個數>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(*)>2
ORDER BY
grade_level DESC;
自連接配接
比如,“查詢員工的名字、上級的名字”
SELECT
e.last_name,
m.last_name
FROM
employees e
JOIN
employees m
ON
e.manger_id=m.employee_id;
外連接配接
應用場景
用于查詢一個表中有,另一個表沒有的記錄
特點
- 外連接配接的查詢結果為主表中的所有記錄,如果從表中有和它比對的,則顯示比對的值;如果從表中沒有和它比對的,則顯示null;外連接配接查詢結果=内連接配接結果+主表中有而從表中沒有的記錄
- 左外連接配接,left join左邊的是主表;右外連接配接,right join右邊的是主表
- 左外和右外交換兩個表的順序,可以實作同樣的效果
- 全外連接配接=内連接配接的結果+表1中有但表2沒有的+表2中有但表1沒有的
簡單查詢
比如,“查詢男朋友不在男神表的女神名”
SELECT
b.name
FROM
beauty b
LEFT OUTER JOIN
boys bo
ON
b.boyfriend_id=bo.id
WHERE
bo.id IS NULL;
又如,“查詢哪個部門沒有員工”
左外:
SELECT
d.*,
e.employee_id
FROM
departments d
LEFT OUTER JOIN
employees e
ON
d.department_id=e.department_id
WHERE
e.employee_id IS NULL;
右外:
SELECT
d.*,
e.employee_id
FROM
employees e
RIGHT OUTER JOIN
departments d
ON
d.department_id=e.department_id
WHERE
e.employee_id IS NULL;
全外連接配接(MySQL不支援)
USE
girls;
SELECT
b.*,
bo.*
FULL OUTER JOIN
boys bo
ON
b.boyfriend_id=bo.id;
交叉連接配接(就是笛卡爾乘積)
SELECT
b.*,
bo.*
FROM
beauty b
CROSS JOIN
boys bo;
sql92 vs sql99
- 功能:sql99支援的較多
- 可讀性:sql99實作連接配接條件和篩選條件的分離,可讀性較高