1 合理的书写风格 (如上例,当写一个较复杂的子查询的时候,要合理的添加换行、缩进), 可以借助PL/SQL Developer工具 2 使用小括号 3 主查询和子查询可以是不同表,只要子查询返回的结果主查询可以使用即可 --查询部门名称是"SALES"的员工信息: 分析: 部门名称在dept表中, dept表与emp表是通过deptno联系在一起的. --使用子查询 select * from emp where deptno=(select deptno from dept where dname='SALES'); --使用多表查询 select e.* from emp e, dept d where e.deptno=d.deptno and d.dname='SALES'; 4 可以在主查询的where、select、having、from后都可以放置子查询 a 在select后使用子查询的情况: 查询10号部门员工号, 员工姓名, 部门编号, 部门名称 select e.empno, e.ename, e.deptno,(select dname from dept where deptno=10) from emp e where e.deptno=10; 注意点: 在select后面使用子查询必须保证子查询结果只返回一条记录. b 在having后面使用子查询的情况: 查询部门平均工资高于30号部门平均工资的部门和平均工资 1 先查询30号部门的平均工资 select avg(sal) from emp where deptno=30; 2 查询每个部门的平均工资 select deptno, avg(sal) from emp group by deptno; 3 select deptno, avg(sal) from emp group by deptno having avg(sal) > (select avg(sal) from emp where deptno = 30); 5 不可以在主查询的group by后面放置子查询 (SQL语句的语法规范) 6 强调:在from后面放置的子查询(***), from后面放置是一个集合(表、查询结果) 7 单行子查询只能使用单行操作符, 多行子查询只能使用多行操作符(前面的> < = 都是单行操作符, 接下来说的是多行操作符) 多行操作符有 IN ANY(任意一个) ALL (所有) --查询部门名称为SALES和ACCOUNTING的员工信息 select * from emp where deptno in (select deptno from dept where dname in ('SALES', 'ACCOUNTING'));
--查询薪水比30号部门任意一个(某一个 ANY )员工高的员工信息 select * from emp where sal >(select min(sal) from emp where deptno=30); select * from emp where sal >(select sal from emp where deptno=30); --错误 select * from emp where sal >any(select sal from emp where deptno=30); --查询比30号部门所有人工资高的员工信息 select * from emp where sal>(select max(sal) from emp where deptno=30); select * from emp where sal>all(select sal from emp where deptno=30); 8 一般不在子查询中使用order by, 但在Top-N分析问题中,必须使用order by 9 一般先执行子查询(内查询),再执行主查询(外查询);但是相关子查询除外 10 子查询中的null值 --查询不是老板的员工信息 分析: 可以先查询谁是老板 select distinct mgr from emp; select * from emp where empno not in (select distinct mgr from emp); select * from emp where empno not in (select distinct mgr from emp where mgr is not null);
总结: not in 后面集合中不能出现null empno not in(a, b, null)---> empno!=a and empno!=b and empno!=null;
思考题? 查询员工的姓名、薪水和年薪? select * from ____________; select * from (select ename, sal, sal*12 from emp); 总结: 可以将查询的结果集当成一张表来使用. 也就是说, from后面既可以是表名, 也可以是select查询的结果集. c 在where后使用子查询的情况: --查询比平均工资高的员工的信息? 1 查询平均工资 select avg(sal) from emp; 2 select * from emp where sal>2073; 合成一步: select * from emp where sal>(select avg(sal) from emp); d 在having后使用子查询的情况: --查询最低薪水高于30号部门最低薪水的部门及其最低薪水 1 先得到30部门的最低薪水 select min(sal) from emp where deptno=30; --950 2 得到各个部门的最低薪水 select deptno, min(sal) from emp group by deptno; 3 使用条件进行过滤 select deptno, min(sal) from emp group by deptno having min(sal) > 950; 将三步合并写成: select deptno, min(sal) from emp group by deptno having min(sal) > (select min(sal) from emp where deptno = 30);