单行子查询
单行子查询是只返回一行数据的子查询语句。 查询与smith同一部门的所有员工:
select * from emp where deptno=
(select deptno from emp where ename=?smith?); 注意:数据库执行sql语句是从左到右的顺序来执行的。如果有括号,先执行括号里的。所以建议将能删减最大数据的查询条件放在最左边,这样可以提高数据库的效率。
单行子查询就是指(select deptno from emp where ename=?smith?)只有一行记录。 多行子查询
多行子查询是返回多行数据的子查询语句。
查询和部门号为10的工作(job)相同的员工名、岗位、工资、部门号:
通过select distinct job from emp where deptno=10;得到部门10的工作有三个:distinct关键字是过滤重复的。
将上面语句当做子查询语句:
select * from emp where job in (select distinct job from emp where deptno=10);
注意:这里job不能用=,必须用关键字in,因为用=是表示一条记录,而现在子查询语句是多行数据,必须用in关键字。 在多行子查询中使用all操作符
查询显示工资比部门为30的所有员工的工资高的员工名、工资、部门号。 先用子查询语句查询部门号为30的工资:
select sal from emp where deptno=30;
然后再查询比部门30的工作高的数据:
select ename,sal,deptno from emp where sal>all
(select sal from emp where deptno=30); 我们也可以有第二种写法,比部门30所有员工工资高的,我们可以利用查询部门30的所有员工的最高工资,如果高于最高工资的员工当然就高于部门30的所有员工的工资。
韩顺平主讲
select max(sal) from emp where deptno=30; select ename,sal,deptno from emp
where sal>( select max(sal) from emp where deptno=30); 第二种写法的效率比第一种的写法要高很多。尽量使用函数。 在多行子查询中使用any操作符
查询显示工资比部门30的任意一个员工的工作高的员工的姓名、工资和部门:
select ename,sal,deptno from emp where sal>any (select sal from emp where deptno=30);
还有第二种写法:
select ename,sal,deptno from emp
where sal>( select min(sal) from emp where deptno=30); 多列子查询
就是子查询语句的结果是多列显示。
select deptno,job from emp where ename=?SMITH?;
再次注意:oracle的表名和字段名是不区分大小写,但是字段里的数据是要区分大小写的。
select * from emp where (deptno,job)=
(select deptno,job from emp where ename=?SMITH?); 在from字句中使用子查询
查询如何显示高于自己部门平均工资的员工的信息: 首先查询各个部门的平均工资和部门号:
select deptno,avg(sal) mysal from emp group by deptno;
第二步,将上面的查询结果看做是一张表(子表),然后和emp进行多表查询 select a1.ename,a1.sal,a1.deptno,a2.mysal from emp a1,
(select deptno,avg(sal) mysal from emp group by deptno) a2 where a1.deptno=a2.deptno and a1.sal>a2.mysal;
韩顺平主讲
from字句中子查询的总结
当在from字句中使用子查询时,该子查询会被当做一个视图来对待,因此也称为内嵌视图,当在from字句中使用子查询时,必须设置子查询的别名。 注意:给列取别名时可以加as,给表取别名不能加as。 oracle分页查询
oracle分页有三种:
第一种分页,利用rownum分页:
select a1.*,rownum rn from (select * from emp) a1; a1.*表示显示只子查询的视图的全部列。
查询rn小于10的所有记录:
select a1.*,rownum rn from (select * from emp) a1 where rn<=10; 把上面的sql再次当成一个子表来查询,就能查询rownum大于6的记录: select * from
(select a1.*,rownum rn from (select * from emp) a1 where rownum<=10) where rn>=6;
为什么要这样三层嵌套呢?因为rownum不支持>=符号。
如果要修改显示的列该怎么改呢?只需改最里面的那个视图就可以了。 select * from
(select a1.*,rownum rn from (select ename,sal from emp) a1
where rownum<=10 )
where rn>=6;
韩顺平主讲
一般分页都会根据一个列排序后再分页,一般会对id主键进行排序,再进行分页。排序也只需在最里层视图。 select * from
(select a1.*,rownum rn from
(select ename,sal from emp order by sal) a1 where rownum<=10 )
where rn>=6;
第二种分页,根据rowid来分页,效率最高,但是最复杂的。 第三种分页,按分析函数来分,最简单,但效率很低。 oracle子查询来创建表
将一个查询结果来创建一张表。 create table myemp2 (id,ename,sal) as select empno,ename,sal from emp; 查询emp表中empno、ename、sal三个字段的数据,并且将数据插入新建表emp2表中的id、ename、sal三个字段中。 这是个小技巧,在数据库维护中可以用到,比如将原来的表导出一部分数据放到另一张表中进行分析。
oracle合并查询(实际应用很少用,是oracle独有的功能)
有时在实际应用中,为了合并多个select语句的结果,可以使用集合操作符:union、union all、intersect、minus。 union:
用于取两个结果集的并集。
select ename,sal,job from emp where sal>2500 union select ename,sal,job from emp where job=?MANAGER?;
韩顺平主讲
注意:如果两个结果集有相同的记录,那么就显示一条。没有相同的记录,就会将两个结果集全部显示。
注意:合并查询并不是查询sal>2500和job=?MANAGER?两个条件都满足的记录。 union all:和union功能一样,只是不会取消重复的记录。 intersect:
取两个结果集集合的交集。
minus:
取两个结果集集合的差集。
select ename,sal,job from emp where sal>2500 minus select ename,sal,job from emp where job=?MANAGER?;
就是拿左边的结果集减右边的结果集,显示剩下的结果集。
注意:如果左边的结果集比右边的结果集小,那么什么也不显示,是个null结果集。
韩顺平主讲