oracle第7章学习子查询总汇/整理笔记

第七章 子查询 

学习子查询刚刚开始有点乱,多做题能让头脑的思路变得清晰,学习方法就是多练多想。

1、子查询

    内部查询,放在括号里的查询。
    子查询可以放在 where ,having,from子句里面


2、子查询的类型
    单行子查询,多行子查询,多列子查询


3、单行子查询:值返回一行一列,使用单行运算符(=,>,<,>=,<=,<>)
   子查询中使用分组函数
   在having在使用子查询   
   


4、多行子查询:使用多行运算符,使用多行运算符(IN,ANY,ALL)
   IN:与之前用法一样
   ANY:有一个满足条件即可
   ALL:每一行都要满足条件




5、多列子查询
   在一个表达式内同时和子查询的多个列进行比较,用IN运算符


6、子查询中的空值


7、在from子句中使用子查询


8、ROWNUM
伪列一般可以用来分页,也可以用来搜索定位

9、TOP-N


10、分页

--分页查询一
select * from (select a1.*,rownum rn from (select * from student) a1 where rownum <=5) where rn>=2;

--分页查询二
select a1.* from (select student.*,rownum rn from student where rownum <=5) a1 where rn >=3;

--分页查询三
select a1.* from (select student.*,rownum rn from student) a1 where rn between 3 and 5;







--子查询
SELECT *
FROM emp
WHERE sal >= (SELECT sal FROM emp WHERE ename='JONES') AND ename<>'JONES';


7369 7876
--子查询,单行子查询,放在where子句
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,empno,sal
FROM emp
WHERE sal = (SELECT MIN(sal) FROM emp )


--子查询放在having子句
SELECT deptno,COUNT(empno)
FROM emp
GROUP BY deptno
HAVING COUNT(empno) > (
       SELECT avg(COUNT(empno))
       FROM emp
       GROUP BY deptno              
)


--多行子查询:IN(查询是经理的员工姓名,工资)
SELECT ename,sal
FROM emp
WHERE empno IN (SELECT DISTINCT mgr FROM emp)




--多行子查询:ANY(查询不是10号部门,且工资比10号部门任意员工工资高的员工的姓名,工资,工作岗位)
SELECT ename,sal,job
FROM emp
WHERE deptno<>10 AND sal > ANY (SELECT sal FROM emp WHERE deptno=10)


--多行子查询:ANY(查询不是10号部门,且工资比10号部门任意员工工资低的员工的姓名,工资,工作岗位)
SELECT ename,sal,job
FROM emp
WHERE deptno<>10 AND sal < ANY (SELECT sal FROM emp WHERE deptno=10)


--多行子查询:ALL(查询不是10号部门,且工资比10号部门所有员工工资高的员工的姓名,工资,工作岗位)
SELECT ename,sal,job
FROM emp
WHERE deptno<>10 AND sal > ALL (SELECT sal FROM emp WHERE deptno=10)


--多行子查询:ALL(查询不是10号部门,且工资比10号部门所有员工工资低的员工的姓名,工资,工作岗位)
SELECT ename,sal,job
FROM emp
WHERE deptno<>10 AND sal < ALL (SELECT sal FROM emp WHERE deptno=10)


--多列子查询,同时和子查询的多列进行比较(子查询的结果有多列)
--查询和1981年入职员工的任意一个员工的部门和职位完全相同的员工信息
SELECT ename,empno,sal,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年入职员工的任意一个员工的部门或者职位相同的员工信息
SELECT ename,empno,sal,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值出现在子查询结果,导致整个主查询没有返回结果
SELECT ename,sal,empno
FROM emp
WHERE empno NOT IN (SELECT  nvl(mgr,0) FROM emp)


--比自己所在部门的平均工资高的员工信息
SELECT ename,sal,job,a.avgsal,e.deptno
FROM emp e,(SELECT deptno, AVG(sal) AS avgsal
          FROM emp
          GROUP BY deptno
            )a

 WHERE e.deptno=a.deptno AND e.sal>a.avgsal



-----------------------------子查询---------------------------------------------
1.查询工资比jones高的员工信息
select * from emp where sal>(select sal from emp where ename='JONES')
select * from emp where sal=(select min(sal) from emp)


-----括号内的查询先执行,也就是子查询优于主查询执行---------------
------子查询使用的位置:where    having   from子句


------查询比30号部门员工工资都低的员工信息
------多行运算符和多行子查询------------------------------------------------------------------
select * 
from emp
where sal

select * 
from emp
where sal<(select min(sal) from emp where deptno=30);-----使用组函数实现功能


-----子查询的分类:单行,多行,多列
-----查询部门最低工资比20号部门最低工资高的部门编号和最低工资
select deptno,min(sal)
from emp 
group by deptno
having min(sal)>(select min(sal) from emp where deptno=20)


-----如果子查询返回结果为空,怎么办?凉拌,可以执行
select * from emp where job=(select job from emp where ename='zhangsan');


----------------------------多行子查询,返回一行或者多行---------------------------------------------
in,any,all
-----查询和scott同一个部门的员工信息
select * from emp where deptno in(select deptno from emp where ename='SCOTT')


update emp 
set sal=sal+1000 
where empno in
(select empno from emp where sal in(select min(sal) from emp group by deptno))----子查询一定要用括号括起来


-------------------any的使用-------------
>any():大于最小的,大于其中任意一个就可以了,等同于>min()
-------找出比30号部门员工工资小的员工信息,小于最大的,所以还有一种写法
select * 
from emp
where sal

select * 
from emp
where sal<(select max(sal) from emp where deptno=30)


------------------------all的使用--------------------
>all():大于最大的,就是比任何一个都要大才行,等同于:>max()


------------------------in的使用---------------------------------------


in 是等于任意一个的意思,等同于  =any()
-----------------------多列子查询----------------------------------------------
--需求:查出与allen的job,deptno相同的员工信息
----多个列之间可以进行比较:语法是(column1,column2)=(select column1,column2......)
select * 
from emp
where (job,deptno) in (select job,deptno from emp where ename='ALLEN')---单行用=,多行用in


------找出不是经理的员工---------------------
select * 
from emp
where empno not in(select distinct mgr from emp where mgr is not null);------------ 子查询中有空值,导致比较后为空

----因为所有的条件和空值比较,结果都是空值---,可以在后面加上where子句过滤掉空值



子查询相关练习

--练习1
--1.查询入职日期最早的员工姓名,入职日期
select ename,hiredate
from emp
where hiredate in (select min(emp.hiredate) from emp)


--2.查询工资比SMITH工资高并且工作地点在CHICAGO的员工姓名,工资,部门名称
select e.ename,e.sal,d.dname,d.loc
from emp e,dept d
where e.deptno=d.deptno and d.loc='CHICAGO' and e.sal>(
      select sal
      from emp
      where ename='SMITH'
)


-- 3.查询入职日期比20部门入职日期最早的员工还
--要早的员工姓名,入职日期
select ename,hiredate
from emp
where emp.hiredate<(
      select min(e.hiredate)
      from emp e
      where deptno=20
)


--4.查询部门人数大于所有部门平均人数的的部门
--编号,部门名称,部门人数
select e.deptno,d.dname,count(e.empno)
from emp e,dept d
where e.deptno=d.deptno
group by e.deptno,d.dname
having count(empno)>(
      select avg(count(empno))
      from emp
     group by emp.deptno
      )




select empno,ename,job,sal
from emp
where sal>all(select sal from emp where deptno=10)
and deptno<>0




--练习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 job,ename
from emp
where job=any(
      select job
      from emp
      where deptno=10
) and deptno<>10






--练习3
--1.查询职位及经理和10部门任意一个员工职位及
--经理相同的员工姓名,职位,不包括10部门员工
select ename,job
from emp
where (job,mgr)= any(
      select job,mgr
from emp
where deptno=10
) and deptno<>10


--2.查询职位及经理和10部门任意一个员工职位或
--经理相同的员工姓名,职位,不包括10部门员工
select ename,deptno
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




--练习4
--1.查询比自己职位平均工资高的员工姓名、职位,部门名称,职位平均工资
select e1.ename,e1.job,d.dname,e2.mean_sal
from dept d,(select avg(sal) mean_sal,job from emp group by job) e2,emp e1
where  d.deptno=e1.deptno and e1.sal>e2.mean_sal and e1.job=e2.job




-- 2.查询职位和经理同员工SCOTT或BLAKE完全相同的员工姓名、职位,不包括SCOOT和BLAKE本人。
select e1.ename,e1.job
from emp e1,(select job,mgr from emp where ename='SCOTT' or ename='BLAKE') e2
where (e1.job=e2.job and e1.mgr=e2.mgr) and e1.ename<>'SCOTT' and e1.ename<>'BLAKE'


--3.查询不是经理的员工姓名。
select ename
from emp
where empno not in(
      select j.empno
      from emp e,emp j
      where e.mgr=j.empno
      group by j.empno
)






--练习5
--1.查询入职日期最早的前5名员工姓名,入职日期。
select rownum,ename,hiredate
from emp
where rownum<6 
order by hiredate


--2.查询工作在CHICAGO并且入职日期最早的前2名员工姓名,入职日期。
select rownum ,e.ename,e.hiredate
from emp e,dept d
where e.deptno=d.deptno and rownum<3 and d.loc='CHICAGO'
order by hiredate




--练习6
--1.按照每页显示5条记录,分别查询第1页,第2
--页,第3页信息,要求显示员工姓名、入职日期、部门名称。
select b.*
from (select rownum rn,e.ename,e.hiredate,d.dname
             from emp e,dept d
             where e.deptno=d.deptno
) b
where rn<=2*5 and rn>(2-1)*5






--练习7
--1.按照每页显示5条记录,分别查询工资最高的
--第1页,第2页,第3页信息,要求显示员工姓名、入职日期、部门名称、工资。
select *
from (select rownum rn,b.*
     from (select  e.ename,e.hiredate,d.dname,e.sal
             from emp e,dept d
             where e.deptno=d.deptno
             order by e.sal desc        
             ) b
             where rownum<=2*5
       )bb
where  rownum>(2-1)*5


select * from
(
       select rownum rn,b.*
       from(select e.ename,e.hiredate,d.dname,e.sal
                   from emp e,dept d
                   where e.deptno=d.deptno
                   order by e.sal desc)b
                   where rownum<=2*5
)bb where rownum>=(2-1)*5






--课后作业
--1.查询工资高于编号为7782的员工工资,并且和7369号员
--工从事相同工作的员工的编号、姓名及工资。
select deptno,ename,sal
from emp
where sal> (select sal from emp where empno=7782)
and job in (select job from emp where empno=7369)




--2.查询工资最高的员工姓名和工资。
select sal,ename
from emp
where sal=(
      select max(sal)
      from emp 
)


--3.查询部门最低工资高于10号部门最低工资的部门的编号、
--名称及部门最低工资。
select e1.deptno,d.dname,e1.pinjun
from (select min(sal) pinjun,deptno from emp group by deptno)e1,
(select min(sal) shihao from emp where deptno=10)e2,dept d
where e1.deptno=d.deptno and e1.pinjun>e2.shihao






--4.查询员工工资为其部门最低工资的员工的编号和姓名及工资。
select deptno,ename,sal
from emp
where sal in (select min(sal) from emp group by deptno )




--5.显示经理是KING的员工姓名,工资。
select ename,sal
from emp
where mgr=(select empno from emp where 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 e,dept d
where e.deptno=d.deptno and d.loc='NEW YORK'






-- 8.写 个查询显示和员工SMITH工作在同 个部门的员工姓名,雇用日期,查询结果中排除SMITH。
select ename,hiredate
from emp 
where deptno in(select deptno from emp where ename='SMITH')
and ename<>'SMITH'




--9.写一个查询显示其工资比全体职员平均工资高的员工编号、姓名。
select ename,empno
from emp
where sal>(select avg(sal) from emp )




--10.写一个查询显示其上级领导是King的员工姓名、工资。
select ename,sal
from emp 
where mgr=(select empno from emp where ename='KING')


--11.显示所有工作在RESEARCH部门的员工姓名,职位。
select e.ename,e.job
from emp e,dept d
where e.deptno=d.deptno and d.dname='RESEARCH'


--12.查询每个部门的部门编号、平均工资,要求部门的平
--均工资高于部门20的平均工资。
select deptno,avg(sal)
from emp
where sal>(select avg(sal) from emp where deptno=20 )
group by deptno


--13.查询大于自己部门平均工资的员工姓名,工资,所在
--部门平均工资,高于部门平均工资的额度。
select e1.ename,e1.sal,e1.sal-e2.bumen 差额
from emp e1,(select avg(sal) bumen,deptno from emp group by deptno)e2
where e1.deptno=e2.deptno and e1.sal>e2.bumen






--课后作业
--14. 列出至少有一个雇员的所有部门
select deptno
from emp 
where emp.empno<>0
group by deptno


--15. 列出薪金比 SMITH 多的所有雇员
select *
from emp
where sal>(select sal from emp where ename='SMITH')


--16. 列出入职日期早于其直接上级的所有雇员
select *
from emp e1,emp e2
where e1.mgr=e2.empno and e1.hiredate>e2.hiredate


--17. 找员工姓名和直接上级的名字
select e1.ename,e2.ename
from emp e1,emp e2
where e1.mgr=e2.empno


--18. 显示部门名称和人数
select d.dname,count(e.empno)
from emp e,dept d
where e.deptno=d.deptno 
group by d.dname




--19. 显示每个部门的最高工资的员工
select max(e.sal),d.dname
from emp e,dept d
where e.deptno=d.deptno
group by d.dname


--20. 显示出和员工号7369部门相同的员工姓名,工资
select ename,sal
from emp
where deptno=(select deptno from emp where empno=7369)


--21. 显示出和姓名中包含"W"的员工相同部门的员工姓名
select ename,deptno
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 e1.ename,e1.sal
from emp e1,(select deptno,avg(sal) pinjun from emp group by deptno) e2
where e1.deptno=e2.deptno and e1.sal>e2.pinjun


--24. 显示每位经理管理员工的最低工资,及最低工资者的姓名
SELECT outer.ENAME FROM EMP outer 
WHERE outer.SAL =(SELECT MIN(SAL) FROM EMP inner where outer.mgr=inner.mgr);--这个地方是用到相关子查询


--用子查询的做法
select ename,empno
from emp
where sal in (select min(sal) from emp  group by mgr ) and ename  is not null




--25. 显示比工资最高的员工参加工作时间晚的员工姓名,参加工作时间
select ename,hiredate
from emp
where hiredate<(select hiredate from emp where sal=(select max(sal) from emp) )


--26. 显示出平均工资最高的的部门平均工资及部门名称




select d.dname,e.zuida
from (select  max(sal) zuida,deptno
     from  emp
     group by deptno
     order by max(sal) desc) e,dept d 
where e.deptno=d.deptno and rownum=1

你可能感兴趣的:(数据库)