04-Oracle复杂查询

1   单行函数:

         · 字符串函数:

                   |- 转大写:字符串 UPPER( | 字符串)

                   |- 转小写:字符串 LOWER( | 字符串)

                   |- 字符串截取:字符串 SUBSTR( | 字符串,开始点 [,截取长度]),起始索引为1

扫描二维码关注公众号,回复: 269830 查看本文章

         · 数值函数:

                   |- 四舍五入:数字 ROUND( | 数字)

                   |- 求模:数字 MOD(1 | 数字1 , 列2 | 数字2)

         · 日期函数:

                   |- 日期的基本公式:

                            |- 日期 + 数字 = 日期(若干天之后的日期);

                            |- 日期 - 数字 = 日期(若干天之前的日期);

                            |- 日期 - 日期 = 数字(两个日期之间所差的天数);

                   |- 两个日期间的总月数:数字 MONTHS_BETWEEN(日期1,日期2)

         · 转换函数:

                   |- 日期或数字转换为字符串:字符串 TO_CHAR( | 日期 | 数字,转换格式)

                            |- 日期时间:年(yyyy)、月(mm)、日(dd)、时(hh24)、分(mi)、秒(ss);

                            |- 数字描述:任意一位数字(9)、本地货币(L);

         · 通用函数:

                   |- 处理NULL:数字 NVL(列,默认值)

                   |- 多值判断:数据 DECODE( | 数值,匹配内容1,显示内容1... [,默认值])

2   多表查询:不管你怎样进行处理,多表查询永远都会存在有笛卡尔积,是不可能取消掉的,能够处理的只是取消掉显示中的笛卡尔积。表越多笛卡尔积就越大;

         · 只有具备关联的表才可能会进行多表查询,而关联的条件可能是列,也可能是自己设置的范围;

         · 表的连接方式:

                   |- 内连接(等值连接):不满足条件的一概不显示;

                   |- 外连接(左外连接、右外连接、全外连接),在oracle中使用“(+)”;

                            |- 左外连接:字段 = 字段(+)

                            |- 右外连接:字段(+) = 字段;

         · SQL:1999语法实现表的连接操作,所有的数据库通用的做法;

         · 集合操作:UNIONUNION ALLMINUSINTESECT,若干个查询返回的结构必须完全相同;

3   分组统计查询:如果在列上存在有重复数据那么才会考虑进行分组查询操作;

         |- 统计函数:COUNT()AVG()SUM()MAX()MIN()

         |- 利用GROUP BY子句可以实现分组的操作,但是对于分组有若干限制:

                   |- 如果不使用GROUP BY子句分组,则SELECT子句之中只能够出现统计函数;

                   |- 如果使用了GROUP BY子句,则SELECT子句里面可以使用分组字段或者是统计函数;

                   |- 统计函数允许嵌套,嵌套之后的SELECT子句里面不允许出现任何字段,包括分组字段。

         |- GROUP BY子句是在WHERE子句之后执行的,所以WHERE子句无法使用统计函数,对分组后的数据进行过滤,则可以使用HAVING子句。

 

 

1子查询返回单行单列,统计出公司的最低工资

select * from emp

where sal=(select min(sal) from emp);

 

 

2子查询返回单行多列,查询出与SCOTT工资相同,职位相同的所有雇员信息

select sal,job from emp where ename='SCOTT' ;

 

select * from emp

where (sal,job)=(

    select sal,job from emp where ename='SCOTT')

    and ename<>'SCOTT';

 

IN操作指的是内容可以在指定的范围之中存在

select * from emp

where sal in(

    select sal from emp where job='MANAGER');

对于IN操作还可以使用NOT IN进行

select * from emp

where sal not in(

select sal from emp where job='MANAGER');

 

曾经说过一个问题, NOT IN不能够为null

select * from emp

where comm not in(

select comm from emp);

 

对于ANY操作实质上有三种子语法:=ANY:功能上与IN是完全没有任何区别的

select * from emp

where sal=any(

select sal from emp where job='MANAGER');

 

>ANY:比子查询返回的最小的内容要大

select * from emp

where sal>any(

select sal from emp where job='MANAGER');

 

<ANY:比子查询中返回最大的值要小

select * from emp

where sal<any(

select sal from emp where job='MANAGER');

 

ALL操作有两种使用形式, >ALL比子查询返回最大的值要大

select * from emp

where sal > all(

select sal from emp where job='MANAGER');

 

<ALL:比子查询中返回的最小的值还要小

select * from emp

where sal < all(

select sal from emp where job='MANAGER');

 

exists()判断,如果现在子查询有数据返回(不管什么数据)就表示条件满足,那么就可以显示出数据,否则不显示。deptno=99不存在

select * from emp

where exists(

select * from emp where deptno=99);

 

select * from emp

where exists(

select * from emp where empno='7839');

 

如果要使用到HAVING那么必须要结合GROUP BY子句,而如果要使用GROUP BY子句就一定要分组

3要求统计出所有高于公司平均工资的部门编号、平均工资、部门人数

select deptno,count(*),avg(sal)

from emp

group by deptno;

 

select deptno,count(*),avg(sal)

from emp

group by deptno

having avg(sal)>(

select avg(sal) from emp);

 

4查询每个雇员的编号、姓名、职位、部门名称

select e.empno,e.ename,e.job,d.dname

from emp e,dept d

where e.deptno=d.deptno;

而现在可以利用子查询,在SELECT子句里面简化操作

select e.empno,e.ename,e.job,

  (select dname d from dept d where d.deptno=e.deptno)

from emp e;

 

5查询出每个部门的编号、名称、位置、部门人数、平均工资

select d.deptno,d.dname,d.loc,count(*),avg(sal)

from emp e,dept d

where e.deptno(+)=d.deptno

group by d.deptno,d.dname,d.loc;

但是除了以上的方式之外,也可以利用子查询完成。

       首先dept是一张数据表,但是对于数据的统计查询,也可以将其定义为一张表

select deptno,count(*),avg(sal)

from emp

group by deptno;

此时的查询返回的是一个多行多列的数据,那么只要是多行多列,就一定可以在FROM子句中出现

select d.deptno,d.dname,d.loc,temp.count,temp.avg

from dept d,(

  select deptno,count(empno) count,avg(sal) avg

  from emp

  group by deptno) temp

where d.deptno=temp.deptno(+);

 

6复杂查询:第一步:找到30部门所有雇员的薪金

select sal from emp where deptno=30;

使用“>ALL:比子查询返回最大的值要大

select e.ename,e.sal

from emp e

where e.sal>all(

select sal from emp where deptno=30);

 

要找到部门的信息,自然在FROM子句之后引入dept表,而后要消除笛卡尔积。用内连接

select e.ename,e.sal,d.dname

from emp e,dept d

where e.sal > all(

select sal from emp where deptno=30)

and e.deptno=d.deptno;

 

· 如果要进行部门的人数统计,那么一定要按照部门分组;

                   · 在使用分组的时候,SELECT子句只能够出现分组字段与统计函数。

         于是此时就出现了一个矛盾,因为SELECT子句里面有其他的字段,所以不可能直接使用GROUP BY分组,所以可以考虑利用子查询分组,即:在FROM子句之后使用子查询先进行分组统计,而后将临时表继续采用多表查询操作

select e.ename,e.sal,d.dname,temp.count

from emp e,dept d,(

select deptno dno,count(empno) count

from emp

group by deptno) temp

where e.sal > all(

select sal from emp where deptno=30)

and e.deptno=d.deptno

and d.deptno=temp.dno;

 

7列出与“SCOTT”从事相同工作的所有员工及部门名称,部门人数,领导姓名

第一步:没有SCOTT的工作就无法知道那个雇员满足条件,需要找到SCOTT的工作

select job from emp where ename='SCOTT';

 

第二步:以上的查询返回的是单行单列,所以只能够在WHERE或者是HAVING中使用,那么根据现在的需求肯定在WHERE中使用,对所有的雇员信息进行筛选

select e.empno,e.ename,e.job

from emp e

where job=(

select job from emp where ename='SCOTT');

 

第三步:如果不需要重复信息,那么可以删除SCOTT

select e.empno,e.ename,e.job

from emp e

where job=(

select job from emp where ename='SCOTT')

and e.ename<>'SCOTT';

 

第四步:部门名称只需要加入dept表即可

select e.empno,e.ename,e.job,d.dname

from emp e,dept d

where job=(

select job from emp where ename='SCOTT')

and e.ename<>'SCOTT'

and e.deptno=d.deptno;

 

第五步:此时的查询不可能直接使用GROUP BY进行分组,所以需要使用子查询实现分组

select e.empno,e.ename,e.job,d.dname,temp.count

from emp e,dept d,(

select deptno dno,count(ename) count

from emp

group by deptno) temp

where job=(

select job from emp where ename='SCOTT')

and e.ename<>'SCOTT'

and e.deptno=d.deptno

and d.deptno=temp.dno;

 

第六步:找到对应的领导信息,直接使用自身关联

select e.empno,e.ename,e.job,d.dname,temp.count,m.ename

from emp e,dept d,(

select deptno dno,count(empno) count

from emp

group by deptno) temp,emp m

where e.job=(

select job from emp where ename='SCOTT')

and e.ename<>'SCOTT'

and e.deptno=d.deptno

and d.deptno=temp.dno

and e.mgr=m.empno;

 

8列出薪金比“SMITH”或“ALLEN”多的所有员工的编号、姓名、部门名称、其领导姓名,部门人数,平均工资、最高及最低工资

|- 雇员与部门:emp.deptno=dept.deptno

|- 雇员与领导:emp.mgr=memp.empno

第一步:知道“SMITH”或“ALLEN”,这个查询返回多行单列(WHERE中使用)

select sal from emp where ename in('SMITH','ALLEN');

 

第二步:现在应该比里面的任意一个多即可,但是要去掉两个雇员。由于是多行单列子查询,所以使用>ANY完成

select e.empno,e.ename,e.sal

from emp e

where e.sal>any(

select sal from emp

where ename in('SMITH','ALLEN'))

and e.ename not in('SMITH','ALLEN');

 

第三步:找到部门名称

select e.empno,e.ename,e.sal,d.dname

from emp e,dept d

where e.sal>any(

select sal

from emp

where ename in('SMITH','ALLEN'))

and e.ename not in('SMITH','ALLEN')

and e.deptno=d.deptno;

 

第四步:找到领导信息

select e.empno,e.ename,e.sal,d.dname,m.ename

from emp e,dept d,emp m

where e.sal>any(

select sal from emp

where ename in('SMITH','ALLEN'))

and e.ename not in('SMITH','ALLEN')

and e.deptno=d.deptno

and e.mgr=m.empno(+);

第五步:部门人数,平均工资、最高及最低工资。整个查询里面不能够直接使用GROUP BY,所以现在应该利用子查询实现统计操作

select e.empno,e.ename,e.sal,d.dname,m.ename,temp.count,temp.avg,temp.max,temp.min

from emp e,dept d,emp m,(

select deptno dno,count(empno) count,avg(sal) avg,max(sal) max,min(sal)min

from emp

group by deptno) temp

where e.sal>any(

select sal from emp

where ename in('SMITH','ALLEN'))

and e.ename not in('SMITH','ALLEN')

and e.deptno=d.deptno

and e.mgr=m.empno(+)

and d.deptno=temp.dno;

 

9列出受雇日期早于其直接上级的所有员工的编号、姓名、部门名称、部门位置、部门人数。

select e.empno,e.ename

from emp e,emp m

where e.mgr=m.empno(+) and e.hiredate<m.hiredate;


第二步:找到部门信息

select e.empno,e.ename,d.dname,d.loc

from emp e,dept d,emp m

where e.mgr=m.empno(+) and e.hiredate<m.hiredate

and e.deptno=d.deptno;

 

第三步:统计部门人数

select e.empno,e.ename,d.dname,d.loc,temp.count

from emp e,emp m,dept d,(

select deptno dno,count(empno) count

from emp

group by deptno) temp

where e.mgr=m.empno(+) and e.hiredate<m.hiredate

    and e.deptno=d.deptno

    and d.deptno=temp.dno;

 

10列出所有“CLERK”(办事员)的姓名及其部门名称,部门的人数,工资等级

· 确定要使用的数据表:

              |- emp表:姓名;

              |- dept表:部门名称;

              |- emp表:统计部门人数;

              |- salgrade表:得到工资等级。

       · 确定已知的关联字段:

              |- 雇员与部门:emp.deptno=dept.deptno

              |- 雇员与工资等级:emp.sal BETWEEN salgrade.losal AND salgrade.hisal

第一步:找到所有办事员的信息

select e.ename from emp e where e.job='CLERK';

第二步:找到部门名称

select e.ename,d.dname

from emp e,dept d

where e.job='CLERK' and e.deptno=d.deptno;

第三步:统计出部门人数

select e.ename 姓名,d.dname dept表部门名称,temp.人数

from emp e,dept d,(

select deptno dno,count(empno) 人数

from emp

group by deptno) temp

where e.job='CLERK' and e.deptno=d.deptno

     and d.deptno=temp.dno;

 

第四步:找到工资等级

select e.ename,d.dname,temp.count,s.grade

from emp e,dept d,(

select deptno dno,count(empno) count

from emp

group by deptno) temp,salgrade s

where e.job='CLERK' and e.deptno=d.deptno

     and d.deptno=temp.dno

     and e.sal between s.losal and s.hisal;

-----------------------------------------

select e.ename 姓名,d.dname dept表部门,temp.人数,s.grade 工资等级

from emp e,dept d,(

select deptno dno,count(empno) 人数

from emp

group by deptno) temp,salgrade s

where e.job='CLERK' and e.deptno=d.deptno

      and d.deptno=temp.dno

      and e.sal between s.losal and s.hisal;

 

猜你喜欢

转载自404168219.iteye.com/blog/2337626
今日推荐