9.子查询
1.子查询介绍:
(1).含义:
出现在其他语句中的select语句, 称为子查询或内查询(其他语句包括但不限于SQL的增删改查语句), 内部嵌套其他select语句的查询, 称为外查询或主查询.
(2).分类:
1 1).按子查询的出现位置: 2 select后面:标量子查询 3 from后面:支持表子查询 4 where或having后面:\*****标量子查询(单行子查询)\*****,列子查询(多行子查询),行子查询(行子查询用的较少) 5 exits后面
6 2).按结果集的行列数不同: 7 标量子查询(结果集只有一行一列) 8 列子查询(结果集只有一列多行) 9 行子查询(结果集有一行多列) 10 表子查询(结果集一般为多行多列)
(3).特点:
1 (1).子查询放在小括号内 2 (2).子查询一般放在条件的右侧 3 (3).标量子查询,一般搭配着单行操作符使用:>,<,=,>=,<=,<> 4 列子查询,一般搭配多行操作符使用:in, any/some, all 5 (4).子查询的执行优先于主查询,主查询要应用子查询的结果
2.出现where和having后面的子查询
(1)标量子查询(单行子查询)
1 # 案例1: 查询谁的工资比Abel高
2 # 分析: 3 1).查询出Abel的工资 4 select salary 5 from employees 6 where last_name='Abel'; 7 2).查询员工信息,筛选条件为工资大于上面的查询结果(最后整合的查询语句) 8 select* 9 from employees 10 where salary>( 11 select salary 12 from employees 13 where last_name ='Able' 14 );
15 # 案例1最后的查询语句: 16 select* 17 from employees 18 where salary>( 19 select salary 20 from employees 21 where last_name ='Able' 22 );
1 # 案例2: 返回job_id与141号员工相同, salary比143号员工多的员工的姓名, job_id和工资
2 # 分析: 3 1).查询141号员工的job_id 4 select job_id 5 from employees 6 where employee_id=141; 7 2).查询143号员工的工资 8 select salary 9 from employees 10 where employee_id=143; 11 3).查询员工的姓名, job_id,工资,筛选条件为job_id等于1的查询结果,工资大于2的查询结果 12 select last_name, job_id, salary 13 from employees 14 where job_id =( 15 select job_id 16 from employees 17 where employee_id=141 18 )and salary >( 19 select salary 20 from employees 21 where employee_id=143 22 );
23 # 案例2最后的查询语句: 24 select last_name, job_id, salary 25 from employees 26 where job_id =( 27 select job_id 28 from employees 29 where employee_id=141 30 )and salary >( 31 select salary 32 from employees 33 where employee_id=143 34 );
1 # 案例3: 返回工资工资最少的员工的last_name, job_id 和 salary
2 # 分析: 3 1).查询公司的最低工资 4 select min(salary) 5 from employees; 6 2).查询员工的名字, job_id, salary,筛选条件是工资等于上面的查询结果 7 select last_name, job_id, salary 8 from empl0yees 9 where salary =( 10 select min(salary) 11 from employees 12 );
13 # 案例3最后查询语句: 14 select last_name, job_id, salary 15 from empl0yees 16 where salary =( 17 select min(salary) 18 from employees 19 );
1 # 案例4: 查询最低工资大于50号部门最低工资的部门id和其最低工资 2 # 分析: 3 1).查询50号部门的最低工资 4 select min(salary) 5 from employees 6 where department_id =50; 7 2).查询出各部门最低工资 8 select min(salary), department_id 9 from employees 10 groupby department_id 11 3)查询部门和该最低工资,筛选条件为其最低工资大于上面的查询结果 12 select min(salary), department_id 13 from employees 14 groupby department_id 15 having ( 16 select min(salary) 17 from employees 18 where department_id =50 19 );
20 # 案例4最后查询语句: 21 select min(salary), department_id 22 from employees 23 groupby department_id 24 having ( 25 select min(salary) 26 from employees 27 where department_id =50 28 );
(注意: 非法使用标量子查询:子查询结果不是一行一列, 会出现查询错误)
(2)列子查询(多行子查询)
1 多行子查询: 2 -返回多行数据 3 -使用多行比较操作符:in/notin等于列表中的任意一个 4 any / some 和子查询返回的某一个值比较 5 all 和子查询返回的所有值比较
6 # 案例1: 返回location_id是1400或1700的部门中的所有员工姓名
7 # 分析: 8 1).查询location_id是1400或1700的部门 9 select department_id 10 from departments as d 11 where d.location_id in(1400,1700); 12 2).查询所有的员工姓名,筛选条件为:员工的部门id在上面的查询结果中 13 select last_name 14 from employees as e 15 where e.department_id in( 16 select department_id 17 from departments as d 18 wherer d.location_id in(1400,1700) 19 );
20 # 案例1的最终查询语句为: 21 select last_name 22 from employees as e 23 where e.department_id in( 24 select department_id 25 from departments as d 26 wherer d.location_id in(1400,1700) 27 );
1 # 案例2: 返回其他工种中比job_id为`IT_PROG`工种任一工资低的员工的员工号, 姓名, job_id以及salary
2 # 分析: 3 1).查询job_id为`IT_PROG`的工种的所有工资 4 select distinct salary 5 from employees 6 where job_id =`IT_PROG`; 7 2).查询其他员工的员工号,名字, job_id, salary,筛选条件为员工的工资低于上面结果的任一值 8 select employee_id, last_name, job_id, salary 9 from employees as e 10 where e.salary < any( 11 select salary 12 from employees 13 where job_id =`IT_PROG` 14 )and job_id<>'IT_PROG';
15 # 案例2的最终查询语句为: 16 select employee_id, last_name, job_id, salary 17 from employees as e 18 where e.salary < any( 19 select salary 20 from employees 21 where job_id =`IT_PROG` 22 )and job_id<>'IT_PROG';
1 # 案例3:返回其他部门中比job_id为`IT_PROG`部门所有工资都低的员工的员工号, 姓名, job_id以及salary 2 select last_name, employee_id, job_id, salary 3 from employees 4 where salary < all( 5 select distinct salary 6 from employees 7 where job_id=`IT_PROG` 8 )and job_id <>`IT_PROG`;
(3)行子查询(用的较少)
1 # 案例: 查询员工编号最小并且工资最高的员工信息 2 select * 3 from employees 4 where(employee_id, salary)=( 5 select min(employee_id), max(salary) 6 from employees 7 );
3.子查询位于select后面
1 # 案例: 查询每个部门的员工个数 2 select d.*,( 3 select count(*) 4 from employees as e 5 where e.department_id = d.department_id 6 )个数 7 from departments as d;
4.子查询位于from后面
1 # 案例: 查询每个部门的平均工资的工资等级
2 # 分析: 3 1).查询每个部门的平均工资 4 select avg(salary), department_id 5 from employees as e 6 groupby department_id; 7 2)在上面的查询结果的基础上连表查询 8 select ag_dep.*, g.grade_level 9 from( 10 select avg(salary)as ag, department_id # 该表中有两个字段, ag(平均工资), 部门id 11 from employees as e 12 groupby department_id; 13 )as ag_dep 14 inner join job_grades as j 15 on ag_dep.ag between j.lowest_sal and highest_sal;# 连接条件是部门平均工资在工资级别表的相应范围
5.子查询放在exists后面(相关子查询)
1 1.语法: 2 exists(完整的查询语句) 3 2.结果:返回布尔值,1或0 4 3.执行顺序:先执行主查询,再根据子查询来过滤主查询的结果
5 # 案例: 查询有员工的部门的部门名 6 select department_name 7 from departments as d 8 where exists( 9 select* 10 from employees as e 11 where d.department_id = e.department_id 12 );
浙公网安备 33010602011771号