一、子查詢含義
出現在其他語句中的select語句,稱為子查詢或內查詢。
二、子查詢分類
按子查詢的位置分
| 位置 | 支持的查詢 |
|---|---|
SELECT后面 |
支持標量子查詢 |
FROM后面 |
支持表子查詢 |
WHERE或HAVING后面 |
支持標量子查詢、列子查詢和行子查詢 |
EXISTS后面 |
支持表子查詢 |
按結果集的行列數不同分
| 分類類型 | 結果集行數 |
|---|---|
| 標量子查詢 | 一行一列 |
| 列子查詢 | 一列多行 |
| 行子查詢 | 一行多列 |
| 表子查詢 | 多行多列 |
三、WHERE后面的子查詢
1. 標量子查詢
tips: 單行操作符(> < =等)只能搭配標量子查詢
查詢工資比Abel高的所有員工信息
①查詢Abel的工資
SELECT salary
FROM employees
WHERE last_name = 'Abel';
結果為單行單列:
②查詢員工的信息,滿足salary>①
查詢公司工資最少的員工的last_name, job_id, salary:
①查詢MIN(salary)
SELECT MIN(salary)
FROM employees;
②查詢符號這項工資的員工,salary=①
SELECT last_name, job_id, salary
FROM employees
WHERE salary=(
SELECT MIN(salary)
FROM employees
);
查詢job_id與141號員工相同,salary比143號員工多的員工的姓名,job_id和工資
①141號員工的job_id
SELECT job_id
FROM employees
WHERE employee_id=141;
②143號員工的salary
SELECT salary
FROM employees
WHERE employee_id=143;
③ 結果集映射到last_name, job_id, salary,且滿足條件 job_id=①和salary>②
SELECT last_name, job_id, salary
FROM employees
WHERE job_id=(
SELECT job_id
FROM employees
WHERE employee_id=141
)AND salary>(
SELECT salary
FROM employees
WHERE employee_id=143
);
2. 列子查詢(多行子查詢)
使用多行操作符:
IN/NOT ININ()等價於=ANY()NOT IN()等價於<>ALL()
ANY/SOMEALL
返回location_id是1400或1700的部門中的所有員工姓名
使用聯表查詢操作得到結果:
SELECT last_name
FROM departments d INNER JOIN employees e
ON d.department_id = e.department_id
WHERE d.location_id IN (1400, 1700);
使用列子查詢得到結果:
①查詢location_id是1400或1700的所有部門的編號
SELECT department_id
FROM departments
WHERE location_id IN (1400, 1700);
②查詢滿足部門編號在列表內的員工的姓名
SELECT last_name
FROM employees
WHERE department_id IN(
SELECT department_id
FROM departments
WHERE location_id IN (1400, 1700)
);
查詢其他工種中的
比job_id為IT_PROG工種的任一員工工資低的
員工的:工號,姓名
①獲取IT_PROG工種所有工資
SELECT DISTINCT salary
FROM employees
WHERE job_id='IT_PROG'
②查詢其他部門中符合條件salary<min(①)的員工信息
SELECT job_id, last_name
FROM employees
WHERE salary < ANY(
SELECT DISTINCT salary
FROM employees
WHERE job_id='IT_PROG'
) AND job_id!='IT_PROG';
3. 行子查詢(結果為一行多列或多行多列)
查詢員工編號最小而且工資最高的員工信息
①查詢最小的員工編號
SELECT MIN(employee_id)
FROM employees;
②查詢員工的最高工資
SELECT MAX(salary)
FROM employees;
③查詢符合employee_id=①,salary=②的員工
SELECT *
FROM employees
WHERE employee_id=(
SELECT MIN(employee_id)
FROM employees
)AND salary=(
SELECT MAX(salary)
FROM employees
);
使用行子查詢的等價寫法:
SELECT *
FROM employees
WHERE (employee_id, salary) = (
SELECT MIN(employee_id), MAX(salary)
FROM employees
);
四 、SELECT后面的子查詢
查詢每個部門的員工個數
使用聯表查詢操作:
SELECT department_name 部門名, COUNT(1) 員工數量
FROM employees e RIGHT JOIN departments d
ON e.department_id = d.department_id
GROUP BY department_name
使用子查詢:
SELECT department_id, department_name,(
SELECT COUNT(1)
FROM employees e
WHERE e.department_id=d.department_id
) 對應員工數
FROM departments d;
在使用子查詢中,外部的表名的別名可以傳遞到子查詢中,例如上面的departments 表的別名d就傳遞到了子查詢中。
該子查詢可以理解為:
- 先獲取
外層查詢的結果集 - 然后對結果集的
每條記錄進行遍歷,將對應的參數填入到子查詢中得到單條記錄的結果拼接到新列中
五、FROM后面的子查詢
查詢每個部門的平均工資的工資等級
①查詢每個部門的平均工資
SELECT AVG(salary) ag,department_id
FROM employees e
WHERE e.department_id IS NOT NULL
GROUP BY department_id;
②查詢對應的工資等級,連接①的結果集和job_grades表
SELECT department_id, ag, grade_level
FROM (
SELECT AVG(salary) ag,department_id
FROM employees e
WHERE e.department_id IS NOT NULL
GROUP BY department_id
) ag_dep INNER JOIN job_grades j
ON ag_dep.ag BETWEEN lowest_sal AND highest_sal;
即可以將子查詢的結果集作為一張表用於聯表查詢操作
六、EXISTS后面的子查詢
EXISTS語句的作用
EXISTS語句后的括號中填入一個子查詢語句,返回的結果為false(0)或true(1),分別代表查詢結果是否為空。
例:
SELECT EXISTS(SELECT employee_id FROM employees);
SELECT EXISTS(SELECT employee_id FROM employees WHERE salary=30000);
簡單應用
查詢有員工的部門名:
SELECT department_name
FROM departments d
WHERE EXISTS(
SELECT *
FROM employees e
WHERE e.department_id = d.department_id
);
這里等價於用IN
SELECT department_name
FROM departments d
WHERE d.department_id IN(
SELECT DISTINCT department_id
FROM employees
);
查詢沒有女票的男神信息
使用EXISTS語句
- 查詢
男神信息 - 篩選條件:他
沒有女票
等價於beauty表中沒有boyfriend_id為當前男生的記錄
等價於beauty表中boyfriend_id為當前男生的id的記錄不存在
SELECT *
FROM boys bo
WHERE NOT EXISTS(
SELECT *
FROM beauty b
WHERE bo.id=b.boyfriend_id
);
使用IN完成相同的任務:
- 查詢
男神信息 - 篩選條件:他
沒有女票
等價於當前男生的id不在beauty表中boyfriend_id字段的集合中
SELECT *
FROM boys b
WHERE b.id NOT IN(
SELECT boyfriend_id
FROM beauty
);
