当一个查询语句中又嵌套了另一个完整的select语句,则
- 被嵌套的
select语句称为子查询或内查询; - 外面的
select语句称为主查询或外查询。
分类
按子查询出现的位置进行分类:
select后面:子查询的结果为单行单列(标量子查询)
from后面:子查询结果可以为多行多列
where或having后面子查询结果必须为单列
- 单行子查询
- 多行子查询
exists后面子查询结果必须为单列(相关子查询)
特点
子查询放在条件中,要求必须放在条件的右侧
子查询必须放在小括号中
子查询的执行优先于主查询
单行子查询对应 单行操作符:
><>=<==<>多行子查询对应 多行操作符:
any/someallin
1. where后面
1. 单行子查询(标量子查询)
# 1. 查询和Zlotkey 相同部门的员工姓名和工资
SELECT last_name,
salary
FROM employees
WHERE department_id = (
SELECT department_id
FROM employees
WHERE last_name = 'Zlotkey'
);
# 2. 查询工资比公司平均工资高的员工的员工号可,姓名和工资
SELECT employee_id,
last_name,
salary
FROM employees
WHERE salary > (
SELECT AVG(salary)
FROM employees
) 2. 多行子查询(列子查询)
in:判断某字段是否在指定列表内any/some: 判断某字段的值是否满足其中任意一个all:判断某字段的值是否满足里面所有的
# 1. 返回location_id 是1400或1700的部门中的所有员工姓名
SELECT last_name
FROM employees
WHERE department_id IN (
SELECT departments.department_id
FROM departments
WHERE location_id IN (1400, 1700)
);
# 2. 返回其他部门中比job_id为`IT_PROG`部门任一工资低的员工的员工号、姓名、job_id以及salary
SELECT employee_id,
last_name,
salary
FROM employees
WHERE salary < ANY (
SELECT DISTINCT salary
FROM employees
WHERE job_id = 'IT_PROG'
)
AND job_id <> 'IT_PROG';
# 即
SELECT employee_id,
last_name,
job_id,
salary
FROM employees
WHERE salary < (
SELECT MAX(salary)
FROM employees
WHERE job_id = 'IT_PROG'
)
AND job_id <> 'IT_PROG';
# 3. 返回其他部门中比job_id为`IT_PROG`部门所有工资低的员工的员工号、姓名、job_id以及salary
SELECT employee_id,
last_name,
job_id,
salary
FROM employees
WHERE salary < ALL (
SELECT DISTINCT salary
FROM employees
WHERE job_id = 'IT_PROG'
)
AND job_id <> 'IT_PROG';
SELECT employee_id,
last_name,
job_id,
salary
FROM employees
WHERE salary < (
SELECT MIN(salary)
FROM employees
WHERE job_id = 'IT_PROG'
)
AND job_id <> 'IT_PROG'; 3. 行子查询(结果集一行多列或多行多列)
# 案例 查询员工编号最小并且工资最高的员工信息
# 1. 查询最小的员工编号
USE myemployees;
SELECT MIN(employee_id)
FROM employees;
# 2. 查询最高工资
SELECT MAX(salary)
FROM employees;
# 3. 查询员工信息
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
); 2. select后面
# 案例1 查询每个部门的员工个数
SELECT d.*, (
SELECT COUNT(*)
FROM employees AS e
WHERE e.department_id = d.department_id
)
FROM departments AS d;
# 案例2 查询员工号=102的部门名
SELECT (
SELECT department_name
FROM departments AS d
INNER JOIN employees AS e
ON d.department_id = e.department_id
WHERE e.employee_id = 102
) 部门名; 括号内只能返回一列。
仅仅支持标量子查询。
3. from后面
充当一个被查询表。
要求必须起别名。
# 案例 查询每个部门的平均工资的工资等级
# 1. 查询每个部门的平均工资
SELECT AVG(salary), department_id
FROM employees
GROUP BY department_id;
-- 工资等级
SELECT * FROM job_grades;
# 2. 连接1的结果集和job_grades表,筛选平均工资
SELECT d.department_name,
avg_dep.*,
g.grade_level
FROM (
SELECT AVG(salary) AS avg_salary, department_id
FROM employees
GROUP BY department_id
) AS avg_dep
INNER JOIN job_grades AS g
ON avg_dep.avg_salary BETWEEN g.lowest_sal AND g.highest_sal
INNER JOIN departments AS d
ON avg_dep.department_id = d.department_id; 4. exists后面(相关子查询)
测试exists
SELECT EXISTS(SELECT employee_id FROM employees);
结果:
| EXISTS(SELECT employee_id FROM employees) |
|---|
| 1 |
即查询查询结果中有没有值。
SELECT EXISTS(SELECT employee_id FROM employees WHERE salary = -1);
结果:
| EXISTS(SELECT employee_id FROM employees WHERE salary = -1) |
|---|
| 0 |
语法
exists(完整的查询语句) ## 结果 # 0 / 1
可以用其他的语句代替,用的比较少。
案例
# 案例1 查询有员工名的部门名
SELECT department_name
FROM departments AS d
WHERE EXISTS(
SELECT *
FROM employees AS e
WHERE d.department_id = e.department_id
);
SELECT department_name
FROM departments AS d
WHERE d.department_id IN (
SELECT department_id
FROM employees
); 
京公网安备 11010502036488号