嵌套在其他语句内部的select语句,称为子查询或内查询。
内部嵌套其他select语句的查询,称为外查询或主查询。
按自查询出现的位置分类:
按结果集的行列数不同:
又称单行子查询,出现在where或having后面
特点
①子查询放在小括号内
②子查询一般放在条件的右侧
③标量子查询,一般搭配单行操作符使用,如> < <>
④列子查询,一般搭配着多行操作符使用 如:in、any all
⑤子查询的执行优先于主查询,主查询的条件用到了子查询的结果。
案例1:谁的工资比Abel高
①首先先查询下Abel的工资
SELECT salary
FROM employees
WHERE last_name='Abel';
②在查询员工的信息,要求salary>①的结果
select * from employees
where salary>(
SELECT salary
FROM employees
WHERE last_name='Abel'
);
案例2:返回job_id与143号员工相同,salary比143号员工多的姓名、job_id,和工资
①首先先去查询,143号员工的job_id
SELECT job_id
FROM employees
WHERE employee_id=143;
②在接着查询143号员工的工资
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=143
)
AND salary>(
SELECT salary
FROM employees
WHERE employee_id=143
);
案例3:返回公司工资最少的员工的last_name,job_id,salary
①首先先查询公司的最低工资
select min(salary)
from employees;
②其次查询last_name,job_id,salary,要求salary=①结果
select last_name,job_id,salary
from employees
where salary=(
SELECT MIN(salary)
FROM employees
);
案例4:查询最低工资大于50号部门的最低工资的部门id和其最低工资
①查询50号部门的最低工资
SELECT MIN(salary)
FROM employees
WHERE department_id=50;
②查询每个部门的最低工资
select min(salary)
from employees
group by department_id;
③在②的基础上筛选,满足min(salary)>①
SELECT MIN(salary),department_id
FROM employees
GROUP BY department_id
having min(salary)>(
select min(salary)
from employees
where department_id=50
);
又称多行子查询,需搭配多行比较操作符使用
操作符 | 含义 |
---|---|
IN/NOT IN | 等于列表中的任意一个 |
ANY|SOME | 和子查询返回的某一个值比较 |
ALL | 和子查询返回的所有值比较 |
案例1:返回location_id是1400或1700的部门中的所有员工姓名
①先查询部门编号为1400或1700下的location_id都有哪些组成一个表(一列多行)
select distinct department_id
from departments
where location_id in (1400,1700);
②查询员工姓名,要求部门编号是①列表中的任意一个
SELECT last_name
FROM employees
WHERE department_id IN (
SELECT DISTINCT department_id
FROM departments
WHERE location_id IN (1400,1700)
);
案例2:返回其他部门中比job_id为‘IT_PROG’部门任一工资低的员工的:工号、姓名、job_id,以及salary
①首先先查询job_id=‘IT_PROG’的所有员工的工资
SELECT DISTINCT salary
FROM employees
WHERE job_id='IT_PROG';
②查询员工的工号、姓名、job_id,以及salary,要求salary<①结果中的任意一个
select employee_id,last_name,job_id,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';
结果集为一行多列或多行多列
案例:查询员工编号最小并且工资最高的员工信息
①查询最小的员工编号
SELECT MIN(employee_id)
FROM employees;
②查询最高工资
SELECT MAX(salary)
FROM employees;
③查询员工信息
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 d.*,(
SELECT COUNT(*)
FROM employees e
WHERE e.department_id=d.department_id
)员工个数
FROM departments d;
查询员工号=102的部门名
SELECT(
SELECT d.department_name
FROM departments d
INNER JOIN employees e
ON d.department_id=e.department_id
WHERE e.employee_id=102
);
支持表子查询
将子查询结果充当一张表,要求必须给表起别名
案例:查询每个部门的平均工资
①先查询每个部门的平均工资
SELECT AVG(salary),department_id
FROM employees
GROUP BY department_id;
②连接①的结果集,和job_grades表,筛选出平均工资between lowest_sal and higest_sal
SELECT ag_dep.*,g.`grade_level`
FROM (
SELECT AVG(salary) ag,department_id
FROM employees
GROUP BY department_id
) ag_dep
INNER JOIN job_grades g
ON ag_dep.ag BETWEEN g.`lowest_sal` AND g.`highest_sal`
又称相关子查询
支持标量子查询、列子查询、行子查询、表子查询
select exists(select employee_id from employees);
结果为1或者0
案例: 查询有员工的部门名
SELECT department_name
FROM departments d
WHERE EXISTS(
SELECT *
FROM employees e
WHERE d.`department_id`=e.`department_id`
);
使用IN关键字
SELECT department_name
FROM departments d
WHERE d.`department_id` IN (
SELECT department_id
FROM employees
)
练习题:
1、查询和ZlotKey相同部门的员工姓名和工资
①先查询员工ZlotKey所在的部门
SELECT department_id
FROM employees
WHERE last_name='ZlotKey';
②查询员工姓名、工资,要求此员工的部门=①的结果
SELECT last_name,salary
FROM employees
WHERE department_id =(
SELECT department_id
FROM employees
WHERE last_name='ZlotKey'
);
2、查询工资比公司平均工资高的员工的员工号、姓名和工资
①查询平均工资
SELECT AVG(salary)
FROM employees;
②查询工资大于①的员工号、姓名、工资
SELECT employee_id,last_name,salary
FROM employees
WHERE salary > (
SELECT AVG(salary)
FROM employees
);
3、查询各部门中工资比本部门平均工资高的员工的员工号,姓名,工资
①查询各部门的平均工资
select avg(salary),department_id
from employees
group by department_id;
②连接①的结果集和employees表
SELECT employee_id,last_name,salary,e.department_id
FROM employees e
INNER JOIN (
SELECT AVG(salary) ag,department_id
FROM employees
GROUP BY department_id
) ag_dep
ON e.`department_id`=ag_dep.department_id
WHERE salary >ag_dep.ag;
4、查询和姓名中包含字母u的员工在相同部门的员工的员工号和姓名
①查询姓名中包含字母u的员工所在部门
SELECT DISTINCT department_id
FROM employees
WHERE last_name LIKE('%u%');
②查询员工的员工号、姓名,要求此员工所在的部门号等于①的结果
select employee_id,last_name
from employees
where department_id in(
SELECT DISTINCT department_id
FROM employees
WHERE last_name LIKE('%u%')
);
5、查询部门的location_id为1700的部门工作的员工的员工号
①查询location_id=1700的部门有哪些
select distinct department_id
from departments
where location_id=1700;
②查询部门号=①的中任意一个的员工号
select employee_id
from employees
where department_id = ANy(
SELECT DISTINCT department_id
FROM departments
WHERE location_id=1700
);
6、查询管理者为King的员工的姓名和工资
①查询姓名为King的员工号
select employee_id
from employees
where last_name ='K_ing';
②查询哪个员工的manager_id等于①的employee_id
select last_name,salary
from employees
where manager_id in(
SELECT employee_id
FROM employees
WHERE last_name ='K_ing'
);
7、查询工资最高的员工的姓名、要求first_name和last_name显示为一列,姓,名
①查询最高工资
SELECT MAX(salary)
FROM employees;
②查询工资=①的员工的姓,名
SELECT CONCAT(first_name,last_name) "姓,名"
FROM employees
WHERE salary=(
SELECT MAX(salary)
FROM employees
);
子查询经典案例题
一、查询工资最低的员工信息:last_name,salry
#①先查询最低工资
SELECT MIN(salary)
FROM employees;
#②查询last_name,salary要求salary=①的结果
SELECT last_name,salary
FROM employees
WHERE salary=(
SELECT MIN(salary)
FROM employees
);
二、查询平均工资最低的部门信息
#①各部门的平均工资
SELECT MIN(salary),department_id
FROM employees
GROUP BY department_id;
#②查询①结果上的最低平均工资
SELECT MIN(ag),
FROM (
SELECT MIN(salary) ag,department_id
FROM employees
GROUP BY department_id
)ag_dep;
#③求出最低平均工资的部门编号
SELECT MIN(salary),department_id
FROM employees
GROUP BY department_id
ORDER BY MIN(salary)
LIMIT 1;
#④查询部门信息
SELECT * FROM
departments
WHERE department_id =(
SELECT department_id
FROM employees
GROUP BY department_id
ORDER BY MIN(salary)
LIMIT 1
);
三、查询平均工资最低的部门信息和该部门的平均工资
SELECT d.*,ag
FROM departments d
INNER JOIN (
SELECT department_id,AVG(salary)ag
FROM employees
GROUP BY department_id
ORDER BY MIN(salary)
LIMIT 1
) ag_dep
ON d.`department_id`=ag_dep.department_id;
四、查询平均工资最高的job信息
#①查询每个job的平均工资
SELECT AVG(salary),job_id
FROM employees
GROUP BY job_id;
#②查询job_id最高的平均工资
SELECT AVG(salary),job_id
FROM employees
GROUP BY job_id
ORDER BY AVG(salary) DESC
LIMIT 1;
#③查询job信息
SELECT *
FROM jobs
WHERE job_id=(
SELECT job_id
FROM employees
GROUP BY job_id
ORDER BY AVG(salary) DESC
LIMIT 1
);
五、查询平均工资高于公司平均工资的部门有哪些
#①先去查询公司的总的平均工资
SELECT AVG(salary) FROM employees;
#②查询每个部门的平均工资
SELECT AVG(salary),department_id
FROM employees
GROUP BY department_id;
#③ 筛选②结果集,要求平均工资>①
SELECT AVG(salary),department_id
FROM employees
GROUP BY department_id
HAVING AVG(salary)>(
SELECT AVG(salary) FROM employees
);
六、查询公司中所有的manager的详细信息
#①查询所有manager的员工编号
SELECT DISTINCT manager_id
FROM employees;
#②查询详细信息,要求manager_id=①中的任意一个
SELECT *
FROM employees
WHERE employee_id= ANY(
SELECT DISTINCT manager_id
FROM employees
);
七、各部门中最高工资中最低的那个部门的最低工资是多少
#①查询各部门的最高工资中最低的部门编号
SELECT DISTINCT department_id
FROM employees;
GROUP BY department_id
ORDER BY MAX(salary)
LIMIT 1;
#②查询①结果的那个部门的最低工资
SELECT MIN(salary),department_id
FROM employees;
WHERE department_id=(
SELECT DISTINCT department_id
FROM employees;
GROUP BY department_id
ORDER BY MAX(salary)
LIMIT 1
);
八、查询平均工资最高的部门的manager的详细信息:last_name,department_id,salary,email
#①查询平均工资最高的部门编号
SELECT department_id
FROM employees
GROUP BY department_id
ORDER BY AVG(salary)DESC
LIMIT 1;
#②将employees 与 departments表连接,筛选条件=①
SELECT last_name,e.department_id,salary,email
FROM employees e
INNER JOIN departments d
ON e.`employee_id`=d.`manager_id`
WHERE d.department_id =(
SELECT department_id
FROM employees
GROUP BY department_id
ORDER BY AVG(salary)DESC
LIMIT 1
);