17/12/6 子查询
单行子查询
- 括号内的查询叫做子查询,也叫内部查询,先于主查询的执行。
- 子查询可以嵌入1.where 2.having 3.from子句中
练习1:
1.查询入职日期最早的员工姓名,入职日期。
select ename, hiredate
from emp
where hiredate = (SELECT min(hiredate)
from EMP)
2.查询工资比SMITH工资高并且工作地点在CHICAGO的员工姓名,工资,部门名称。
select ename, sal, dept.dname
from emp
join dept on emp.deptno = dept.deptno
where sal > (select sal
from emp
where ename = 'SMITH')
and dept.loc = 'CHICAGO'
3.查询入职日期比20部门入职日期最早的员工还要早的员工姓名,入职日期。
select ename, hiredate
from emp
where hiredate < (select min(hiredate)
from emp
where deptno = 20)
4.查询部门人数大于所有部门平均人数的部门编号,部门名称,部门人数。
select emp.deptno, dname, count(*)
from emp
join dept on dept.deptno = emp.deptno
group by emp.deptno, dname
HAVING count(*) > (select avg(count(*))
from emp
group by emp.deptno)
多行子查询
-子查询返回的条数,可以是一套或多条
-和多行子查询进行比较时,需要使用多行操作符.
in:
any: 表示和子查询的任意
一行结果进行比较,有一个满足条件即可。
<li>< any: 表示小于子查询结果集中的任意一个,即小于最大值就可以。
<li>> any: 反之,大于最小值即可。
<li>= any: 相当于IN。
all: 表示和子查询的所有
行记过进行比较,每一行必须满足条件。
<li>< all: 表示小于子查询结果集中的所有行,即小于最小值。
<li>>all: 反之,大于最大值。
<li>=all: 无意义。
练习2
1.查询入职日期比10部门任意一个员工晚的员工姓名、入职日期,不包括10部门员工。
select ename, hiredate
from emp
where hiredate >any (select hiredate
from emp
where deptno=10)
and deptno <> 10
2.查询入职日期比10部门任意一个员工晚的员工姓名、入职日期,不包括10部门的员工。
select ename, hiredate
from emp
where hiredate >all (select hiredate
from emp
where deptno=10)
and deptno <> 10
3.查询职位和10部门任意一个员工职位相同的员工姓名,职位,不包括10部门员工。
select ename, job
from emp
where job in (select job
from emp
where deptno=10)
and deptno <> 10
多列子查询
-之前讲的子查询都是在一个条件表达式内和子查询的一个列进行比较,多列子查询可以在一个条件表达式内同时和子查询的多个列进行比较。
-多列子查询通常用IN操作符完成。
练习3
1.查询职位及经理和10部门任意一个员工职位及经理相同的员工姓名,职位,不包括10部门员工。
select ename, job
from emp
where (job, mgr) in (select job,mgr
from emp
where deptno=10)
and deptno <> 10
2.查询职位及经理和10部门任意一个员工职位或经理相同的员工姓名,职位,不包括10部门员工。
select ename, job
from emp
where (job in (select job
from emp
where deptno=10)
or MGR IN(select mgr
from emp
where deptno=10))
and deptno<>10
子查询中的空值
无论什么时候只要空值有可能成为子查询结果的一部分,就不能使用NOT IN运算符。
在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
练习4:
1.查询比自己职位平均工资高的员工姓名、职位,部门名称,职位平均工资。
select a.ename, a.job, dept.deptno, b.salavg
from emp a, dept, (select job, avg(sal) salavg
from emp
group by job) b
where a.job = b.job and a.DEPTNO = DEPT.DEPTNO
and a.sal > b.salavg
2.查询职位和经理同员工SCOTT或BLACK完全相同的员工姓名、职位、不包括SCOTT和BLAKE本人。
方法1:多列子查询
select ename, job
from emp
where (job, mgr) in (
select job, mgr
from emp
where ename in('SCOTT','BLAKE') )
and ename not in ('SCOTT','BLAKE')
方法2:建立一个与'SCOTT' ,'BLAKE'的职位和经理的临时表,然后与emp建立连接,过滤掉与SCOTT 与 BLAKE 职位经理不同的行。
select ename,EMP.job
from EMP
join
(select job,mgr
from emp
where ename in ('SCOTT','BLAKE')) tempTab
on EMP.job = TEMPTAB.job and EMP.MGR = TEMPTAB.mgr
where ename not in ('SCOTT','BLAKE')
ROWNUM(伪列)
TOP-N查询
练习5
1.查询入职日期最早的前5名员工姓名,入职日期
SELECT ROWNUM, ename, hiredate
FROM(SELECT ename,hiredate
from emp
ORDER BY hiredate) demptab
where ROWNUM < =2
2.查询工作在CHICAGO并且入职日期最早的前两名员工姓名,入职日期。
SELECT ROWNUM, ename, hiredate
FROM(SELECT ename,hiredate,deptno
from emp
ORDER BY hiredate) demptab
join dept on dept.deptno = DEMPTAB.DEPTNO
where ROWNUM < =2 and dept.loc = 'CHICAGO'
分页
练习7
1.按照每页显示5条记录,分别查询工资最高的第一页,第二页,第三页信息,要求显示员工姓名、入职日期、部门名称、工资。
方法1:
第一页
select *
from (select rownum rn, *
from emp join dept on emp.deptno= dept.deptno
order by sal desc) b
where rn>0 and rn <=5
方法2:
select tempTab2.ENAME,tempTab2.HIREDATE,DEPT.DNAME,TEMPTAB2.sal
from
(select rownum rn, tempTab.* from (select * from emp order by sal desc) tempTab where rownum <= 15) tempTab2
join dept on DEPT.deptno = tempTab2.deptno
where tempTab2.rn > 10
第二页,第三页。。。
课后作业
1.查询工资高于编号为7782的员工工资,并且和7369号员工从事相同工作的员工的编号、姓名及工资。
select empno, ename, sal
from emp
where sal>(select sal
from emp
where empno=7782) and
job = (select job
from emp
where empno=7369)
2.查询工资最高的员工姓名和工资。
select ename, sal
from emp
where sal = (select max(sal)
from emp)
3.查询部门最低工资高于10号部门最低工资的部门的编号、名称及部门最低工资。
select EMP.deptno, DEPT.dname, min(sal)
from emp
join dept on emp.deptno = dept.deptno
group by EMP.deptno, dept.dname
having min(sal) > (select min(sal)
from emp
where deptno=10)
4.查询员工工资为其部门最低工资的员工的编号和姓名及工资。
select empno, ename, sal
from emp
join dept on emp.deptno = dept.deptno
where sal in (select min(sal)
from emp
group by deptno )
5.显示经理是KING的员工姓名,工资。
select a.ename, a.sal
from emp a
join emp b on a.mgr = b.empno
where b.ename = 'KING'
6.显示比员工SMITH参加工作时间晚的员工姓名,工资,参加工作时间。
select ename, sal, hiredate
from emp
where hiredate > (select hiredate
from emp
where ename = 'SMITH')
7.使用子查询的方式查询那些职员在NEW YORK工作。
select ename
from emp
join dept on emp.deptno = dept.deptno
where loc = 'NEW YORK'
8.写一个查询显示和员工SMITH工作在同一个部门的员工姓名,雇佣日期,查询结果中排除SMITH。
select ename, hiredate
from emp
where deptno = (select deptno
from emp
where ename='SMITH')
and ename <> 'SMITH'
9.写一个查询显示其工资比全体职员平均工资高的员工编号、姓名。
select empno, ename
from emp
where sal > (select avg(sal)
from emp)
10.写一个查询显示其上级领导是King的员工姓名、工资。
select a.ename, a.sal
from emp a
join emp b on a.mgr = b.empno
where a.mgr = (select empno
from emp
where ename = 'KING')
11.显示所有工作在RESEARCH部门的员工姓名,职位。
select ename, job
from emp
join dept on emp.deptno = dept.deptno
where dept.dname = 'RESEARCH'
12.查询每个部门的部门编号、平均工资,要求部门的平均工资高于部门20的平均工资。
select deptno, avg(sal)
from emp
group by deptno
where avg(sal) > (select avg(sal)
from emp
group by deptno)
13.查询大于自己部门
平均工资的员工姓名,工资,所在 部门平均工资,高于部门平均工资的额度。
select e.ename, e.sal, b.avgsal, e.sal-b.avgsal
from emp e
join(select deptno,avg(sal) avgsal
from emp
group by deptno) b on e.deptno = b.deptno
where e.sal>b.avgsal
注:b.avg(sal) 必须得起别名。
14.列出至少有一个雇员的所有部门。
select deptno, count(*)
from emp
group by deptno
15.列出薪金比"SMITH"多的所有雇员.
select ename
from emp
where sal > (select sal
from emp
WHERE ename = 'SMITH')
16.列出入职日期早于其直接上级的所有雇员.
select
from emp woker
join emp manager on woker.mgr = manager
17.找员工姓名和直接上级的名字。
select woker.ename , manager.ename
from emp woker
join emp manager on woker.mgr = manager.empno
18.显示部门名称和人数
select dname, nvl(count(empno),0)
from emp
right join dept on emp.deptno = dept.deptno
group by dname
19.显示每个部门的最高工资的员工
方法1:
SELECT *
FROM EMP
WHERE (DEPTNO,SAL) IN (SELECT DEPTNO,MAX(SAL) FROM EMP GROUP BY DEPTNO)
方法2:
select *
from emp a
join(select deptno, max(sal) maxsal
from emp
group by deptno) b on a.deptno = b.deptno and a.sal = b.maxsal
20.显示出和员工号7369部门相同的员工姓名,工资
select ename, sal
from emp
where deptno = (select deptno
from emp
where empno = 7369) and empno <> 7369
21.显示出和姓名中包含"W"的员工相同部门的员工姓名
select ename
from emp
where deptno = (select deptno
from emp
where ename like '%W%' )
22.显示出工资大于平均工资的员工姓名,工资
select ename ,sal
from emp
where sal > (select avg(sal)
from emp )
23.显示出工资大于本部门平均工资的员工姓名 工资
select ename, sal
from emp a
join(select DEPTNO, avg(sal) avgsal
from emp
group by deptno) b
on a.deptno = b.deptno
where a.sal > b.avgsal
24.显示每位经理管理员工的最低工资,及最低工资者的姓名。
方法1:
select EMP.ename,EMP.sal
from EMP
join (select EMP.mgr, min(sal) minsal
from EMP
GROUP BY EMP.mgr) tempTab on EMP.mgr = tempTab.mgr and EMP.sal = tempTab.minsal
方法2:
select sal, ename
from emp
where (mgr, sal) in (select mgr, min(sal)
from emp
group by mgr)
25.显示比工资最高的员工参加工作时间晚的员工姓名,参加
工作时间
select ename, HIREDATE
from emp
where hiredate >(select hiredate
from emp
where sal =(select max(sal) from emp))
26.显示出平均工资最高的的部门平均工资及部门名称
SELECT dname, avgsal
from dept d
join(select deptno, avg(sal) avgsal
from emp
GROUP BY deptno) temptab on d.deptno = TEMPTAB.DEPTNO
where avgsal = (select max(avg(sal))
from emp
group by deptno)