– 子查询
1.子查询(内部查询)优先于主查询(外部查询)执行
2.子查询的结果被主查询使用
– 单行子查询
-- 查询出比JONES工资高的其他雇员
select ename
from emp
where sal > (select sal from emp where ename = 'JONES');
– 注意:查询的值需在表中存在,如输入ename = ‘JONEs’是没有数据返回的,
– 因为’JONEs’在ename列中不存在
– 列名对大小写不敏感,而列值对大小写敏感
-- 显示和雇员7369从事相同工作并且工资大于雇员7876的雇员的姓名和工作
select ename, job
from emp
where job = (select job from emp where empno = 7369)
and sal > (select sal from emp where empno = 7876);
– 子查询中使用组函数
-- 查询工资最低的员工姓名,岗位及工资
select ename, job, sal from emp where sal = (select min(sal) from emp);
– 注意在where中与分组的子查询比较将产生错误
-- 查询每个部门的最低工资员工信息
select * from emp
where sal = (select min(sal) from emp group by deptno);
-- 错误,单行运算符与多行子查询不匹配
-- 应使用having子句
– 在having子句中使用子查询
-- 查询部门最低工资比20部门最低工资高的部门编号及最低工资
select deptno, min(sal)
from emp
group by deptno
having min(sal) > (select min(sal) from emp where deptno = 20);
-- 查询哪个部门的员工人数 高于各部门平均人数。
select deptno, count(empno)
from emp
group by deptno
having count(empno) >
(select avg(count(empno)) from emp group by deptno);
– 多行子查询:返回多行一列的值,使用多行运算符:in any all
in 满足其中一个条件
-- 查询是经理的员工姓名,工资 select ename, sal from emp where empno in (select distinct mgr from emp where mgr is not null);
any 满足其中一个条件
-- 查询是经理的员工姓名,工资 select ename, sal from emp where empno = any (select distinct mgr from emp where mgr is not null); -- =any 功能与in一样 -- 查询部门编号不为10,且工资比10部门任意一名员工工资高的员工编号,姓名,职位, -> 工资。 select empno, ename, job, sal from emp where sal > any (select sal from emp where deptno = 10) and deptno <> 10; -- 查询部门编号不为10,且工资比10部门任意一名工资低的员工编号,姓名,职位,工资。 select empno, ename, job, sal from emp where sal < any (select sal from emp where deptno = 10) and deptno <> 10;
all 满足其中所有条件
-- 查询部门编号不为10,且工资比10部门所有员工工资高的员工编号,姓名,职位,工资。 select empno, ename, job, sal from emp where sal > all (select sal from emp where deptno = 10) and deptno <> 10; -- 查询部门编号不为10,且工资比10部门所有员工工资低的员工编号,姓名,职位,工资。 select empno, ename, job, sal from emp where sal < all (select sal from emp where deptno = 10) and deptno <> 10; -- 查询部门编号不为10,且工资和10部门所有员工工资相等的员工编号,姓名, -> 职位,工资。 -- = all 一般无意义 select empno, ename, job, sal from emp where sal = all (select sal from emp where deptno = 10) and deptno <> 10;
– 多列子查询
成对比较 -- 查询出和1981年入职的任意一个员工的部门和职位!!完全相同!!员工姓名、部门、职位、 -> 入职日期, -> 不包括1981年入职员工。 select ename, deptno, job, hiredate from emp where (deptno, job) in --列名之间逗号','隔开,所有列名用()扩号修饰 (select deptno, job from emp where to_char(hiredate, 'YYYY') = '1981') and to_char(hiredate, 'YYYY') <> '1981'; 不成对比较 -- 查询出和1981年入职的任意一个员工的部门!!或职位!!相同员工姓名、部门、职位、 -> 入职日期, -> 不包括1981年入职员工。 不成对比较 select ename, deptno, job, hiredate from emp where (deptno in (select deptno from emp where to_char(hiredate, 'YYYY') = '1981') or job in (select job from emp where to_char(hiredate, 'YYYY') = '1981')) and to_char(hiredate, 'YYYY') <> '1981';
– 子查询中的空值(null)
-- 注意:子查询的结果中有一条空值,这条空值导致主查询没有记录返回。 -> 这是因为所有的条件和空值比较结果都是空值。 -- 因此无论什么时候只要空值有可能成为子查询结果集合中的一部分, -> 就不能使用NOT IN 运算符。 select ename from emp where empno not in (select distinct mgr from emp);
– 在from字句中使用子查询
一般遇到要跟自己比较的都用子查询在from语句中的使用-- 查询比自己部门平均工资高的员工姓名,工资,部门编号,部门平均工资 select a.ename, a.sal, a.deptno, b.salavg from emp a, (select deptno, avg(sal) salavg from emp group by deptno) b where a.deptno = b.deptno and a.sal > b.salavg;
– rownum 伪列: 永远从1开始,只能使用 < 、<=,不能使用>,=,>=,between..and区间运算做比较运算
select rownum,empno, ename, job from emp where rownum <= 5; --rownum可以与order by结合使用 select rownum,e.* from emp e order by rownum desc;
– rowid 伪列,物理存在,唯一标识每一行数据,可以通过rowid修改数据或删除数据
select rowid,e.* from emp e where rowid='AAAR3sAAEAAAACXAAH';
– top-n:查询某列前n条数据,通过rownum伪列来查询
– !!!不是关键字-- 查询员工表中前五名薪资最【高】的员工信息 select rownum,e.* from (select * from emp order by sal desc) e where rownum <= 5; -- 查询员工表中前五名薪资最【低】的员工信息 select rownum,e.* from (select * from emp order by sal asc) e where rownum <= 5
– 分页查询
– 结合子查询在from子句中的使用已知:每页显示5条,当前页数1 1 1-5 2 6-10 3 11-15 4 16-20 开始索引:(当前页码*每页显示条数)-每页显示条数 + 1 = (当前页码-1)*每页显示条数+1 结束索引:当前页码*每页显示条数 select rownum,e.* from emp e where rownum <= 5; --第一页 select * from (select rownum rn,e.* from emp e where rownum <=10) where rn>=6; --第二页 效率高,先选择从1到需要查询的最大值之间的数据,再按要查的页数进行筛选 select * from (select rownum rn,e.* from emp e) where rn<=10 and rn>=6; --第二页 效率低,直接查出所有数据,再进行最小值与最大值的筛选 select * from (select rownum rn,e.* from emp e where rownum <=15) where rn>=11; --第三页 select * from (select rownum rn,e.* from emp e) where rn<=15 and rn>=11; --第三页
–&表示一个变量,beginIndex、endIndex分别为变量名称,可自定义
select * from (select rownum rn,e.* from emp e where rownum <=&endIndex) where rn>=&beginIndex;
–分页排序
在子查询外再嵌套一层子查询,用于查询后数据排序即rownum是按照查询结果的顺序生成的,若直接排序将打乱其顺序
故需要在外层套一层子查询,将排好序的数据重新生成rownum伪列select * from (select rownum rn, e.* from (select * from emp order by sal) e where rownum <= 10) e2 where rn >= 6