[数据库]关于三个比较典型的数据库试题

最近学习Oracle,老师讲了三个比较典型的问题,做一下总结,也便于以后复习.

下图显示的是三个题的题干和要查询的结果:

===========================================第一题============================
找到员工表中工资最高的前三名:

先说明一个现象:

 1 SQL> select rownum,ename from emp;
 2 
 3 ROWNUM ENAME
 4 ---------- ----------
 5 1 SMITH
 6 2 ALLEN
 7 3 WARD
 8 4 JONES
 9 5 MARTIN
10 6 BLAKE
11 7 CLARK
12 8 SCOTT
13 9 KING
14 10 TURNER
15 11 ADAMS
16 12 JAMES
17 13 FORD
18 14 MILLER

如果在加上一些条件限制:

 1 SQL> select rownum ,ename,sal from emp order by sal desc;
 2 
 3     ROWNUM ENAME             SAL
 4 ---------- ---------- ----------
 5          9 KING             5000
 6         13 FORD             3000
 7          8 SCOTT            3000
 8          4 JONES            2975
 9          6 BLAKE            2850
10          7 CLARK            2450
11          2 ALLEN            1600
12         10 TURNER           1500
13         14 MILLER           1300
14          3 WARD             1250
15          5 MARTIN           1250
16         11 ADAMS            1100
17         12 JAMES             950
18          1 SMITH             800

加上order by rownum 依旧没有变化,说明rownum是基于原始表emp进行排序的 ,固定住了.

把这个查询的结果集再看成一个新表select ename,sal from emp order by sal desc

用rownum就会对这个新表进行排序.排序的rownum按照查询的顺序来展示.

select rownum,ename,sal from
    (select ename,sal from emp order by sal desc) 
    where rownum < 4

    ROWNUM ENAME             SAL
---------- ---------- ----------
         1 KING             5000
         2 SCOTT            3000
         3 FORD             3000

===========================================第二题===================================

找到员工表中薪水大于本部门平均薪水的员工

SQL> select e.empno,e.ename,e.sal,d.avgsal
     from  emp e,(select deptno,avg(sal) avgsal from emp group by deptno) d
     where e.deptno=d.deptno and e.sal>d.avgsal;

     EMPNO ENAME             SAL     AVGSAL
---------- ---------- ---------- ----------
      7499 ALLEN            1600 1566.66667
      7566 JONES            2975       2175
      7698 BLAKE            2850 1566.66667
      7788 SCOTT            3000       2175
      7839 KING             5000 2916.66667
      7902 FORD             3000       2175

e.deptno = empavg.deptno and e.sal > empavg.salavg
翻译下来就是:第一个条件是本部门的员工,第二个是薪水大于部门的平均薪水

还有一种不用group by分组函数也能查询到

叫:相关子查询

相关子查询:将主查询中的某些值作为参数传递给子查询.

相关子查询对外边的主表有一个要求,必须有一个别名.

 

先不看上面结果的第四列(AVGSAL),可以很容易的查询到

select empno,ename, sal from emp e

 

然后查询某个部门的平均工资:

select avg(sal) from emp where deptno = ?

 

需要确定这个deptno是什么!

结合上面两个语句

select empno,ename, sal from emp e

where e.sal >( select avg(sal) from emp where deptno = ?)

这个问好?应该代表的是查询的当前员工所在的部门号传给这个问号.

变成:

select empno,ename, sal from emp e

where e.sal > (select avg(sal) from emp where deptno = e.deptno);

 

然后主查询列上要加上所在部门平均工资

把上面的最后一句查询部门的平均工资拷贝到主查询列上.就可以了.

 

SQL> select empno,ename, sal,(select avg( sal) from emp  where deptno = e.deptno) avgsal
      from emp e
      where e.sal>(select avg( sal) from emp  where deptno = e.deptno);

     EMPNO ENAME             SAL     AVGSAL
---------- ---------- ---------- ----------
      7499 ALLEN            1600 1566.66667
      7566 JONES            2975       2175
      7698 BLAKE            2850 1566.66667
      7788 SCOTT            3000       2175
      7839 KING             5000 2916.66667
      7902 FORD             3000       2175

 

===============================================第三题=======================
统计每年入职的员工的个数!

select count(*) from emp where decode(substr(to_char(hiredate,yyyy-mm-dd),3,2)80


decode(substr(to_char(hiredate,"yyyy-mm-dd"),3,4),81,count+1)


SQL> select count(*) ,
2 sum(decode(to_char(hiredate,RR),80,1,0)) "1980",
3 sum(decode(to_char(hiredate,RR),81,1,0)) "1981",
4 sum(decode(to_char(hiredate,RR),87,1,0)) "1987"
5 from emp;

COUNT(*) 1980 1981 1987
---------- ---------- ---------- ----------
14 1 10 2

 



 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。