SQL子查询
一、非关联子查询
(一)子查询
就是在一条SQL语句中嵌入另一条SQL语句
select sal from emp where ename='FORD'; select sal from emp where sal>300; select ename from emp where sal>(select sal from emp where ename='FORD');
1.先执行子查询,子查询的返回结果作为主查询的条件,再执行主查询
2.子查询只执行一遍
3.若子查询的返回结果为多个值,Oracle会去掉重复值之后,再将结果返回给主查询
4.子查询常见错误
(1)比较运算符的选择
(2)若 子查询的返回结果仅为一个值,可用单值运算符,如=,>, <, >=, <=
(3)若子查询的返回结果可能为多值,必须用多值运算符,如IN等
5.若子查询的返回结果中包含空值NULL,并且运算符为NOT IN,那么整个查询不会返回任何行。NOT IN等价于<>ALL,任何值跟NULL比(包括NULL本身),结果都不为TRUE
(二)多列子查询
每个部门薪水最高的人
select deptno,ename,sal from emp where(deptno,sal) in (select deptno,max(sal) sal from emp group by deptno);(三)having子句中包含子查询
select deptno from emp group by deptno having avg(sal)>(select avg(sal) from emp where deptno=20);
二、关联子查询
select c1,c2 from t1 outer where c1 operator(select c1,c2 from tables where expr1=outer.expr2);哪些员工的薪水比本部门的平均薪水高
select ename,sal,deptno from emp outer where sal>(select avg(sal) from emp where deptno=outer.deptno);(一)关联子查询的执行过程
关联子查询采用的是循环的方式,执行步骤如下:
1.外部查询得到一条记录(查询先从outer表中读取数据),并将其传入到内部查询
2.内部查询基于传入的值执行
3.内部查询从其结果中把值传回到外部查询,外部查询使用这些值来完成其处理,若符合条件,outer表中得到的那条记录就放入结果集中,否则放弃,该记录不符合条件
4.重复1~3步,直到把outer表中的所有记录判断一遍
(二)exists运算符
select ename,job,deptno from emp outer where exists(select 'x' from emp where mgr=outer.empno);1.exists的执行过程
exists采用的是循环方式,判断outer表中是否存在记录,只要在innner表中找到一条匹配的记录即可
(1)外部记录得到一条记录(查询先从outer表中读取数据)并将其传入到内部查询的表
(2)对innner表中的记录依次扫描,若根据条件存在一条记录与outer表中的记录匹配,立即停止扫描,返回true,将outer表中的记录放入结果集中,若扫描了全部记录,没有任何一条记录符合匹配条件,返回false,outer表中的该记录被过滤掉,不能出现在结果集中
(3)重复(1)(2),直到把outer表中的所有记录判断一遍
(三)not exists
查询出没有员工的部门
select deptno,dname from dept outer where not exists(select 'x' from emp where deptno=outer.deptno);(四)IN和EXISTS的比较
EXISTS是用循环的方式,由outer表的记录数决定循环的次数,对于exists影响最大,所以,外表的记录数要少
IN先执行子查询,子查询的返回结果去重之后,再执行主查询,所以,子查询的返回结果越少,越适合用该方式。