一、子查詢含義
出現在其他語句中的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 IN
IN()
等價於=ANY()
NOT IN()
等價於<>ALL()
ANY
/SOME
ALL
返回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
);