MySQL 子查询介绍和单行子查询、多行子查询介绍
子查询指一个查询语句嵌套在另一个查询语句内部的查询,这个特性从MySQL 4.1开始引入。
SQL 中子查询的使用大大增强了 SELECT 查询的能力,因为很多时候查询需要从结果集中获取数据,或者需要从同一个表中先计算得出一个数据结果,然后与这个数据结果(可能是某个标量,也可能是某个集合)进行比较。
一、子查询基本使用
1.1、子查询的基本语法结构
Select select_list
From table
Where expr_operator
(select select_list from table);
- 子查询(内查询)在主查询之前一次执行完成。
- 子查询的结果被主查询(外查询)使用。
注意事项
- 子查询要包含在括号内
- 将子查询放在比较条件的右侧
1.2、子查询案例

1、两次独立的查询
SELECT salary
FROM employees
WHERE last_name = 'Abel';
SELECT last_name,salary
FROM employees
WHERE salary > 11000;
2、自连接多表查询
SELECT e2.last_name,e2.salary
FROM employees e1,employees e2
WHERE e1.last_name = 'Abel'
AND e1.`salary` < e2.`salary`
3、子查询方式
SELECT last_name,salary
FROM employees
WHERE salary > (
SELECT salary
FROM employees
WHERE last_name = 'Abel'
);
二、单行子查询和多行子查询
我们按子查询的结果返回一条还是多条记录,将子查询分为单行子查询、多行子查询。
三、单行子查询
子查询的结果返回一条记录的SQL,归类于单行子查询。
3.1、单行比较操作符
操作符 | 含义 |
---|---|
= | equal to |
> | greater than |
>= | greater than or equal to |
< | less than |
<= | less than or equal to |
<> | not equal to |
3.2、子查询中包含MIN聚合函数
返回公司工资最少的员工的last_name,job_id和salary。
SELECT last_name, job_id, salary
FROM employees
WHERE salary =
(SELECT MIN(salary)
FROM employees);
3.3、多个子查询条件
返回job_id与141号员工相同,salary比143号员工多的员工姓名,job_id和工资。
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);
3.4、HAVING 中的子查询
首先执行子查询。向主查询中的HAVING 子句返回结果。
题目:查询最低工资大于50号部门最低工资的部门id和其最低工资。
SELECT department_id, MIN(salary)
FROM employees
GROUP BY department_id
HAVING MIN(salary) >
(SELECT MIN(salary)
FROM employees
WHERE department_id = 50);
3.5、子查询中的空值问题
SELECT last_name, job_id
FROM employees
WHERE job_id =
(SELECT job_id
FROM employees
WHERE last_name = 'Haas');
子查询结果为空:no rows selected
3.6、非法使用子查询
多行子查询使用单行比较符。
SELECT employee_id, last_name
FROM employees
WHERE salary =
(SELECT MIN(salary)
FROM employees
GROUP BY department_id);
3.7、CASE中的子查询
在CASE表达式中使用单列子查询。
显式员工的employee_id,last_name和location。其中,若员工department_id与location_id为1800的department_id相同,则location为’Canada’,其余则为’USA’。
SELECT employee_id, last_name,
(CASE department_id
WHEN
(SELECT department_id FROM departments
WHERE location_id = 1800)
THEN 'Canada' ELSE 'USA' END) location
FROM employees;
四、多行子查询(集合比较子查询)
子查询的结果返回多条记录的SQL,归类于多行子查询。
4.1、多行比较操作符
操作符 | 含义 |
---|---|
IN | 等于列表中的任意一个 |
ANY | 需要和单行比较操作符一起使用,和子查询返回的某一个值比较 |
ALL | 需要和单行比较操作符一起使用,和子查询返回的所有值比较 |
SOME | 实际上是ANY的别名,作用相同,一般常使用ANY |
4.2、ANY 多表查询
返回其它job_id中比job_id为‘IT_PROG’部门任一工资低的员工的员工号、姓名、job_id 以及salary。
Select employee_id,last_name,job_id,salary
From employees
WHERE salary < ANY
(SELECT salary
From employees
WHERE job_id="IT_PROG")
AND job_id <> "IT_PROG";
4.3、ALL 多表查询
返回其它job_id中比job_id为‘IT_PROG’部门所有工资都低的员工的员工号、姓名、job_id以及salary。
Select employee_id,last_name,job_id,salary
From employees
WHERE salary < ALL
(SELECT salary
From employees
WHERE job_id="IT_PROG")
AND job_id <> "IT_PROG";
4.4、不成对比较 和 成对比较
查询与141号或174号员工的manager_id和department_id相同的其他员工的employee_id,manager_id,department_id。
4.4.1、实现方式1:不成对比较
SELECT employee_id, manager_id, department_id
FROM employees
WHERE manager_id IN
(SELECT manager_id
FROM employees
WHERE employee_id IN (174,141))
AND department_id IN
(SELECT department_id
FROM employees
WHERE employee_id IN (174,141))
AND employee_id NOT IN(174,141);
4.4.2、实现方式2:成对比较
SELECT employee_id, manager_id, department_id
FROM employees
WHERE (manager_id, department_id) IN
(SELECT manager_id, department_id
FROM employees
WHERE employee_id IN (141,174))
AND employee_id NOT IN (141,174);