子查询所要解决的问题:问题不能一步求解
SQL> --查询工资比SCOTT高的员工信息
SQL> select *
2 from emp
3 where sal > (select sal
4 from emp
5 where ename='SCOTT');
注意的问题:
1. 将子查询放入括号中
2. 采用合理的书写风格
3. 可以在主查询的where select from having后面,放置子查询
4. 不可以在group by后面放置子查询
5. 强调from后面放置子查询
6. 主查询和子查询可以不是同一张表,只要子查询返回的结果,主查询可以使用,即可
7. 一般不在子查询中使用order by;但在Top-N分析问题中,必须使用order by
8. 一般先执行子查询,再执行主查询;但相关子查询除外
9. 单行子查询只能使用单行操作符(>,<,=);多行子查询只能使用多行操作符(in,any,all)
10. 注意子查询中null
在主查询的 select 后面,放置子查询
SQL> select ename,sal,(select job from emp where empno=7839) myjob
2 from emp;
5. 强调from后面放置子查询
SQL> --查询员工的姓名和薪水
SQL> select *
2 from (select ename,sal from emp);
6. 主查询和子查询可以不是同一张表,只要子查询返回的结果,主查询可以使用,即可
SQL> --查询部门名称为 SALES的员工信息
1 select *
2 from emp
3 where deptno=(select deptno
4 from dept
5 where dname='SALES');
1 select e.*
2 from emp e,dept d
3 where e.deptno=d.deptno and d.dname='SALES';(性能比前一句好)
SQL优化: 如果子查询和多表查询都可以,理论上尽量使用多表查询
多行操作符
--in :在集合中
SQL> --查询部门名称为SALES和ACCOUNTING的员工信息
SQL> select *
2 from emp
3 where deptno in (select deptno from dept where dname='SALES' or dname='ACCOUNTING');
SQL> select e.*
2 from emp e,dept d
3 where e.deptno=d.deptno and (d.dname='SALES' or d.dname='ACCOUNTING');
--any 和集合的任意一个值比较
SQL> --查询工资比30号部门任意一个员工高的员工信息
SQL> select *
2 from emp
3 where sal > any (select sal from emp where deptno=30);
相当于:
1 select *
2 from emp
3* where sal > (select min(sal) from emp where deptno=30)
--all 和集合的所有值比较
SQL> --查询工资比30号部门所有员工高的员工信息
SQL> select *
2 from emp
3 where sal > all (select sal from emp where deptno=30);
相当于:
1 select *
2 from emp
3* where sal > (select max(sal) from emp where deptno=30)
--多行子查询中null值
SQL> select *
2 from emp
3 where empno not in (select mgr from emp);
未选定行-----》错误的结果:因为not in 之后的元素里面,每个元素的逻辑运算是and,
即not in a and not in b and ...not in null
只要有null值,则不会返回结果,其实是有结果的
--查询是老板的员工信息
1 select *
2 from emp
3* where empno in (select mgr from emp)
------------》会产生正确结果:因为in之后的元素之间采用的是or逻辑运算
即in a or in b or...in null
即使有null值,但之前符合的结果还是会被正确返回
--查询不是老板的员工信息
SQL> select *
2 from emp
3 where empno not in (select mgr from emp where mgr is not null);