子查询含义:
出现在其他语句的select语句,称为子查询或内查询
外部的查询语句,称为主查询或外查询
分类:
按子查询出现的位置:
select后面:
仅仅支持标量子查询
from后面:
支持表子查询
where或having后面:★★★
标量子查询(单行)√
列子查询 (多行)√
行子查询(用的少)
exists后面(相关子查询)
表子查询
按结果集的行列数不同:
标量子查询(结果集只有一行一列)
列子查询(结果集一列多行)
行子查询(结果集一行多列)
表子查询(结果集一般为多行多列)
支持:
1.标量子查询(单行子查询)
2.列子查询(多行子查询)
3.行子查询(多行多列)
特点:
①子查询放在小括号内
②子查询一般放在条件的右侧
③标量子查询,一般单行操作符使用>,<,=,>=,<=,<>
列子查询,一般搭配多行操作符使用in,any/sum,all
④子查询的执行优先于主查询的执行,主查询的条件用到了子查询的结果
案例1: 谁的工资比Abel高?
step1:查询Abel的工资
show databases;
use myemployees;
select salary from employees where last_name = 'Abel';
step2:查询员工信息,满足salary>step1的结果
select * from employees
where salary >(
select salary
from employees
where last_name = 'Abel'
); # where后面标量子查询(结果集是一个数据),放在()内
案例2: 返回job_id与141号员工相同,salary比143号员工多的员工姓名,job_id和工资
step1:查询141号员工的job_id
select job_id
from employees
where employee_id=141;
step2:查询143号员工的salary
select salary
from employees
where employee_id=143;
step3:查询员工的姓名,job_id和工资,要求job_id=step1并且salary>step2
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: 返回公司工资最少的员工last_name,job_id,salary
step1:查询公司的最低工资
select min(salary)
from employees;
step2:查询last_name,job_id,和salary,要求salary=step1结果
select last_name,job_id,salary
from employees
where salary=(
select min(salary)
from employees
);
案例4: 查询最低工资大于50号部门最低工资的部门id和其最低工资
step1:查询50号部门的最低工资
select min(salary)
from employees
where department_id=50;
step2:查询每个部门的最低工资
select min(salary),department_id
from employees
group by department_id;
step3:筛选step2满足min(salary)>step1
select min(salary),department_id
from employees
group by department_id
having min(salary)>(
select min(salary)
from employees
where department_id=50
); # 子查询在having之后
非法使用子查询
select min(salary),department_id
from employees
group by department_id
having min(salary)>(
select salary
from employees
where department_id=50
); # 不是一行一列
案例1: 返回location_id是1400或1700的部门中的所有员工姓名
step1:查询location_id是1400或1700的部门编号
select department_id
from departments
where location_id in (1400,1700); # 两行
step2:查询员工姓名,要求部门号是step1列表中的某一个
select last_name
from employees
where department_id in(
select distinct department_id
from departments
where location_id in (1400,1700)
); # 将in换成 =any 效果一样;not in换成<>all效果一样
案例2: 返回其它工种中比job_id为‘IT_PROG’工种部门任一工资低的员工的员工号、姓名、job_id以及salary
step1: 查询job_id为‘IT_PROG’部门任一工资
select distinct salary
from employees
where job_id='IT_PROG';
step2: 查询员工号、姓名、job_id以及salary,salary 或者: 案例3: 返回其它部门中比job_id为‘IT_PROG’部门所有工资都低的员工的员工号、姓名、job_id 以及salary 或 案例: 查询员工编号最小且工资最高的员工信息 传统做法: s2:查询最高工资 s3:查询员工信息 仅仅支持标量子查询 案例2: 查询员工号=102的部门 将子查询结果充当一张表,要求必须起别名 s2:连接s1的结果集和job_grades表,筛选条件平均工资between lowest_sal and highest_sal 语法: 案例1: 查询有员工的部门名 == exists== 案例2: 查询没有女朋友的男神信息 not existsselect last_name,employee_id,job_id,salary
from employees
where salary < any (
select distinct salary
from employees
where job_id='IT_PROG'
)and job_id<>'IT_PROG'; # 工种不是IT_PROG且工资低于IT_PROG任一工资的员工
select last_name,employee_id,job_id,salary
from employees
where salary < (
select max(salary)
from employees
where job_id='IT_PROG'
)and job_id<>'IT_PROG'; # 去掉any,里面为max也行
select last_name,employee_id,job_id,salary
from employees
where salary < all (
select distinct salary
from employees
where job_id='IT_PROG'
)and job_id<>'IT_PROG'; # 比IT_PROG部门所有(all)都低
select last_name,employee_id,job_id,salary
from employees
where salary < (
select min(salary)
from employees
where job_id='IT_PROG'
)and job_id<>'IT_PROG'; # 去掉all,里面为min也行
1.3 行子查询(结果集一行多列或多行多列)
select *
from employees
where (employee_id,salary)=(
select min(employee_id),max(salary)
from employees
);
s1:查询最小的员工编号show databases;
use myemployees;
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
); # 不用and,使两个字段放在()里亦可
二、select后面
案例1: 查询每个部门的员工个数select d.*,(
select count(*)
from employees e
where e.department_id=d.department_id
) 个数 # 个数为标量
from departments d;
select (
select department_name
from departments d
inner join employees e
on d.department_id=e.department_id
where e.employee_id=102
) 部门名; # 里面是部门名
三、from后面
案例: 查询每个部门的平均工资的工资等级
s1:查询每个部门的平均工资select avg(salary),department_id
from employees
group by department_id;
select * from job_grades;
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 lowest_sal and highest_sal;
四、exists后面(相关子查询)
exists(完整的查询语句)
结果:
1:存在,0:不存在select exists(select employee_id from employees where salary = 30000);
in(能使用exists就能用in)select department_name
from departments d
where d.department_id in (
select department_id
from employees
); # 员工表中的部门名集合里是不是部门表中也有
select department_name
from departments d
where exists(
select *
from employees e
where d.department_id=e.department_id
);
not inuse girls;
select bo.*
from boys bo
where bo.id not in(
select boyfriend_id
from beauty
);
select bo.*
from boys bo
where not exists(
select boyfriend_id
from beauty b
where bo.id=b.boyfriend_id
);