持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第12天,点击查看活动详情
前言
上篇我们学习了MySQL子查询中的单行子查询。有兴趣的小伙伴可以阅读(# MySQL学习-单行子查询)。
下面继续学习MySQL子查询中的多行子查询。
多行子查询
- 多行子查询也称为集合比较子查询。
- 内查询返回多行。
- 使用多行比较操作符。
多行比较操作符
| 操作符 | 含义 |
|---|---|
| IN | 等于列表中的任意一个 |
| ANY | 需要和单行比较操作符一起使用,和子查询返回的某一个值比较 |
| ALL | 需要和单行比较操作符一起使用,和子查询返回的所有值比较 |
| SOME | 实际上是ANY的别名,作用相同,一般常使用ANY |
举例一
查询各部门最低工资的员工信息。
这里需先查出各部门的最低工资,因为有不同的部门,所以子查询的结果是多行,这里使用IN。
SELECT employee_id, name
FROM employees
WHERE salary IN (
SELECT MIN(salary)
FROM employees
GROUP BY department_id
);
多行子查询,这里使用IN,就可以查出符合条件的员工信息。
举例二
返回其他job_id中比job_id为'IT'部门任一工资低的员工的员工号、姓名、job_id以及salary。
SELECT employee_id, name, job_id, salary
FROM employees
WHERE job_id <> 'IT'
AND salary < ANY (
SELECT salary
FROM employees
WHERE job_id = 'IT'
);
| employee_id | name | job_id | salary |
|---|---|---|---|
| 2 | xiaolan | HR | 3200.00 |
这里使用ANY,只要其他部门中比IT部门任一值低就可以。
举例三
返回其他job_id中比job_id为'IT'部门所有工资低的员工的员工号、姓名、job_id以及salary。
分析:这里任一改成了所有,需要使用ALL操作符。
SELECT employee_id, name, job_id, salary
FROM employees
WHERE job_id <> 'IT'
AND salary < ALL (
SELECT salary
FROM employees
WHERE job_id = 'IT'
);
| employee_id | name | job_id | salary |
|---|---|---|---|
| 2 | xiaolan | HR | 3200.00 |
举例四
查询平均工资最低的部门id。
分析:首先查询各个部门的平均工资,对部门进行分组。再从平均工资里找最低工资,我们先用AVG平均之后再套用MIN函数的方式试一试。
SELECT MIN(AVG(salary))
FROM employees
GROUP BY department_id
运行发现报错,这是因为MySQL聚合函数外不能再嵌套聚合函数。
结论: MySQL中聚合函数是不能嵌套使用的。
方式1
分析: 不是嵌套聚合函数的话,我们可以把平均工资的结果当成一张新表,然后在新表中查询最低工资。所以正确的写法是。
SELECT MIN(avg_sal)
FROM (
SELECT AVG(salary) avg_sal
FROM employees
GROUP BY department_id
) t_dept_avg_sal;
这样就可以查出最低的工资,然后再查出最低工资所在的部门。
SELECT department_id
FROM employees
GROUP BY department_id
HAVING AVG(salary) = (
SELECT MIN(avg_sal)
FROM (
SELECT AVG(salary) avg_sal
FROM employees
GROUP BY department_id
) t_dept_avg_sal
);
| department_id |
|---|
| 2 |
这样就可以查出结果。
方式2
先查出平均工资,然后找到部门平均工资是最小的值。使用<= ALL的方法,比所有值都小,自然是平均工资中的最小值。
SELECT department_id
FROM employees
GROUP BY department_id
HAVING AVG(salary) <= ALL (
SELECT AVG(salary) avg_sal
FROM employees
GROUP BY department_id
);
| department_id |
|---|
| 2 |
空值问题
SELECT name
FROM employees
WHERE employee_id NOT IN (
SELECT manager_id
FROM employees
);
从SQL语句中可以看出,想查询不是管理者的员工信息,但是运行发现没有结果。实际上不是所有的人都是管理者。为什么没有结果查出来呢?这是以为子查询的结果包含NULL值,所以NOT IN来比较的话,没有结果。这里需要过滤NULL值的情况。正确写法:
SELECT name
FROM employees
WHERE employee_id NOT IN (
SELECT manager_id
FROM employees
WHERE manager_id IS NOT NULL
);
这样就可以查出想要的结果。
今天先学习到这里,明天继续。