Oracle之数据操作__子查询

子查询

 子查询是一个完整的查询语句之中,嵌套若干个不同功能的小查询,从而一起完成查询。

   复杂查询 = 限定查询 +多表查询 + 统计查询 + 子查询

 子查询可以返回的数据类型一共分为四种:

子查询可以返回的数据类型一共分为四种:
        单行单列:返回的是一个具体列的内容,可以理解为一个单值数据
        单行多列:返回一行数据中多个列的内容
        多行单列:返回多行记录之中同一列的内容,相当于给出了一个操作范围
        多行多列:查询返回的结果是一张临时表
#WHERE子句:  此时子查询返回的结果一般都是单行单列,单行多列,多行多列
#HAVING子句: 此时子查询返回的都是单行单列数据,同时为了使用统计函数操作
#FROM子句:   此时子查询返回的结果一般都是多行多列,可以按照一张数据表(临时表)的形式操作

1. 查询公司之中工资最低的雇员的完整信息

SELECT * FROM emp WHERE sal=(select min(sal) from emp);

二 在WHERE子句中使用子查询

A.返回单行单列

 1. 查询基本工资比“二宝”低的全部雇员信息

SELECT * FROM emp WHERE sal<(select sal from emp where ename='二宝');
View Code

2. 查询基本工资高于公司平均薪金的全部雇员信息

SELECT * FROM emp WHERE sal>(select avg(sal) from emp);
View Code

3.查询出与‘’李四‘’从事同一份工作,并且基本工资高于雇员7521(不包括李四)的全部雇员信息

SELECT * FROM emp
WHERE job=(select job from emp where ename='李四')
AND   sal>(select sal from emp where empno=7521)
AND   ename<>'李四';
View Code

     

B. 返回单行多列 

1. 查询与‘风清扬’从事同一份工作且工资相同的雇员信息(不包括风清扬)

SELECT * FROM emp
WHERE (job,sal)=(select job,sal from emp where ename='风清扬')
AND ename<>'风清扬';
View Code

2. 查询与雇员7749从事同一工作且领导相同的全部信息

SELECT * FROM emp 
WHERE (job,mgr)=(SELECT job,mgr FROM emp WHERE empno=7749);
View Code

3. 查询与‘’李四‘从事同一工作且在同一年雇佣的全部雇员信息’(包括李四)

SELECT * FROM emp
WHERE (job,TO_CHAR(hiredate,'yyyy'))=(
             SELECT job,TO_CHAR(hiredate,'yyyy') FROM emp WHERE ename='李四');
View Code

C. 返回多行单列数据

  主要使用 IN,ANY,ALL

## IN

1.查询出与每个部门中最低工资的全部信息

SELECT * FROM emp 
WHERE sal IN (select min(sal) from emp group by did);
View Code

注意:关于null的问题,如果在IN之中子查询返回的数据有null,那么不会有影响。如果在 NOT IN 之中子查询返回的数据有null,那么就不会有任何数据返回。

select * from emp where empno not in ( select mgr from emp );

    

## ANY

        

1.操作准备:首先找出每个部门经理的最低工资(考虑一个部门可能有多个经理)

SELECT min(sal) FROM emp WHERE job='MANAGER' group by did;

          

1.1. 然后:

SELECT sal FROM emp 
WHERE sal=ANY(
    select min(sal) from emp where job='MANAGER' group by did
);

                  

1.2. 发现1,1.1的结果,一样

2.  >ANY操作(最小的是 1111)

SELECT * FROM emp
WHERE sal>ANY(select min(sal) from emp where job='MANAGER' group by did);

         

 D. exists结构

    空数据判断,在SQL之中,提供了 exists结构用于判断子查询是否有数据返回。如果子查询有数据返回,则exists结构返回 true,否则为 false

1.

SELECT * FROM emp 
WHERE  exists (
    select * from emp where empno=9999
);

           

#由于不存在 9999 编号的雇员,所以在这里 exists()判断返回就是false,就不会有结果返回

2.使用 not

select * from emp
where not exists(
    select * from emp where empno=9999
);

三 在HAVING子句中使用子查询

    HAVING 一定是结合GROUP BY 子句一起使用的,其主要的目的是进行分组后数据再次过滤,而且与WHERE子句不同的是,HAVING是在分组后,可以使用统计函数。

1.查询部门编号,雇员人数,平均工资,并且要求部门的平均工资高于公司平均工资

SELECT did,count(empno),avg(sal) FROM emp
GROUP BY did
HAVING avg(sal)>(select avg(sal) from emp);
View Code

2. 查询出每个部门平均工资最高的部门名称及平均工资

select d.dname,round(avg(e.sal),2)
from emp e,dept d
where e.did=d.did
group by d.dname 
having avg(sal)=(select max(avg(sal)) from emp group by did);
View Code

四 在FROM子句中使用子查询

1. 要求查询出每个部门的编号,名称,位置,部门人数,平均工资

SELECT d.did,d.dname,d.loc,temp.人数 ,temp.平均工资
FROM dept d,(select did di,COUNT(empno) 人数,ROUND(avg(sal),2) 平均工资 FROM emp GROUP BY did) temp
WHERE d.did=temp.di(+);
View Code

                      

 2. 查询出所有在 '公关部 '部门工作的员工的编号,姓名,基本工资,奖金,职位,雇佣日期,部门的最高和最低工资

select e.empno,e.ename,e.sal,e.comm,e.job,e.hiredate,temp.max,temp.min
from emp e,(select did dd,MAX(sal) max,MIN(sal) min from emp GROUP BY did) temp 
WHERE e.did=(select did from dept where dname='公关部') AND e.did=temp.dd;
View Code

          

 #提示:(select did dd,MAX(sal) max,MIN(sal) min from emp GROUP BY did) temp ---> 子查询负责统计信息,使用temp表示临时的统计结果

3. 查询出所有薪金高于公司平均薪金的员工编号,姓名,基本工资,职位,雇佣日期,所在部门名称,位置,上级领导名称,公司的工资等级,部门人数,平均工资,平均服务年限

SELECT e.empno,e.ename,e.sal,e.job,e.hiredate,d.loc,m.ename
FROM emp e,dept d,emp m,salgrade s,(select did dd,count(empno) count,
              round(avg(months_between(sysdate,hiredate)/12),1) avgyear from emp group by did) temp
WHERE e.sal>(select avg(sal) from emp) 
AND e.did=d.did
AND e.mgr=m.empno(+)
AND e.sal BETWEEN s.losal AND s.hisal
AND e.did=temp.dd;
View Code

4. 查询薪金比 ‘张三’ 或 ‘如花’ 多的所有员工的编号,姓名,基本工资,部门名称,其领导姓名,部门人数

SELECT e.empno,e.ename,e.sal,d.dname,m.ename 领导姓名,temp.count
FROM emp e,dept d,emp m,(select did dd,count(empno) count from emp group by did) temp
WHERE e.sal>ANY(select sal from emp where ename in('张三','如花'))
AND e.did=d.did 
AND e.mgr=m.empno(+)
AND temp.dd=d.did
AND e.ename NOT IN('张三','如花');
View Code

 5. 列出公司各个部门的经理(假设每个部门只有一个经理,job为 “MANAGER”)的姓名,薪金,部门名称,部门人数,部门平均工资

SELECT e.ename,e.sal,d.dname,temp.count,temp.avg
FROM emp e,dept d,(select did dd,count(empno) count,round(avg(sal),2) avg from emp group by did) temp
WHERE job='MANAGER'
AND e.did=d.did
AND e.did=temp.dd;
View Code

五 在SELECT子句中使用子查询(了解)

 1.查询出公司每个部门的编号,名称,位置,部门人数,平均工资

SELECT did,dname,loc,
    (select count(empno) from emp where did=d.did group by did) count,
    (select round(avg(empno),2) from emp where did=d.did group by did) avg
FROM dept d;
View Code

2.不分组也可以

SELECT did,dname,loc,
    (select count(empno) from emp where did=d.did ) count,
    (select round(avg(empno),2) from emp where did=d.did ) avg
FROM dept d;
View Code

                                    

六 WITH子句

    临时表实际上就是一个查询结果,如果一个查询结果返回的是多行多列。那么就可以将其定义在FROM字句之中,表示为一张临时表。除了在FROM子句之中出现临时表之外,也可以利用WITH子句直接定义临时表,就可以绕开了FROM子句。

1.使用WITH子句将emp表中的数据定义为临时表

WITH e AS(select * from emp)
SELECT * FROM e;

2.查询每个部门的编号,名称,位置,部门平均工资,人数

WITH e AS (select did dd,round(avg(sal),2) avg,count(sal) count from emp group by did)
SELECT d.did,d.dname,d.loc,e.count,e.avg FROM e,dept d
WHERE e.dd(+)=d.did;
View Code

3.查询每个部门工资最高的雇员编号,姓名,职位,雇用日期,工资,部门编号,部门名称,显示的结果按照部门编号进行排序

WITH e AS (select did dd,max(sal) max from emp group by did)
SELECT em.empno,em.ename,em.job,em.hiredate,em.sal,d.did,d.dname
FROM e,emp em,dept d
WHERE e.dd=em.did
AND em.sal=e.max
AND e.dd=d.did
ORDER BY d.did;
View Code

                                  

原文地址:https://www.cnblogs.com/zhaochangbo/p/8407332.html