Oracle作业4-函数
一、在数据库中的emp和dept表中做如下查询:
1.列出所有分析师(analyst)的姓名、编号和部门
select ename,empno,e.deptno,dname from emp e,dept d where upper(job)='analyst' and e.deptno=d.deptno;
2.找出佣金高于薪金的雇员
select empno,ename,sal,comm from emp where nvl(comm,0)>sal;--为了避免用null值进行比较,使用nvl函数
3.找出部门10中所有经理和部门20中的所有分析师(analyst)的详细资料
select * from emp where job='manager' and deptno=10 or job='analyst' and deptno=20;
4.找出各月最后一天受雇的所有雇员
分析:emp表中的hiredate为date数据类型,数据格式为:1980/12/17;last_day(hiredate)的值为1980/12/31,也是date类型,故两者格式相同,可进行是否相等的比较
select * from emp where hiredate = last_day(hiredate); --没有满足条件的查询结果
5.找出早于25年之前受雇的雇员
select * from emp where (months_between(sysdate,hiredate)/12)>25;
6.显示只有首字母大写的所有雇员的姓名
select ename from emp where initcap(ename)=ename; -- 没有满足条件的查询结果
7.显示所有雇员的姓名的前三个字符
select substr(ename,1,3) 姓名前三个字符 from emp;
8.显示所有雇员的姓名,用a替换所有'a'
select replace(ename,'a','a') 员工姓名 from emp;
9.显示所有雇员的姓名以及满10年服务年限的日期
select ename 员工姓名,hiredate 受雇日期,add_months(hiredate,10*12) 工作十周年日 from emp;
10.列出所有员工及直接上级的姓名
思路:由于mgr字段存在一个叫king的终极大boss是没有上级的,所以在自连接时,为了将其也显示出来,不能用e.mgr=m.empno,所以采用左自连接将为空的那行也显示出来。
select e.empno,e.ename,e.job,e.mgr,m.ename 上级姓名 from emp e,emp m where e.mgr=m.empno(+) order by e.empno; --上面的左自连接查询可以用下面的左外连接查询实现 select e.empno,e.ename,e.job,e.mgr,m.ename 上级姓名 from emp e left join emp m on e.mgr=m.empno order by e.empno;
二、综合题:
1.取得部门中(所有人的)平均的薪水等级
思路:查询得到各部门的平均薪水这个查询结果(后面把这个查询结果简称为a),然后从a、salgrade表和dept表中根据a中平均薪水在salgrade表的相应区间以及a中部门编号与部门表的关联关系获取到相应的薪水等级和部门名称等相关查询结果。
select t.deptno,d.dname,t.asal,grade from salgrade,(select avg(sal) asal,deptno from emp group by deptno order by deptno)t,dept d where t.asal between losal and hisal and d.deptno=t.deptno;
2.取得平均薪水最高的部门的部门编号
思路:最关键是查询得到各部门的平均工资这个结果(后面把这个查询结果简称为a),这个查询结果在下面的sql语句中出现了两次,后面出现的a是为了从中获取最高平均工资这个结果,然后为前面的查询提供条件,而前面的a是为了从中查询到满足题目要求的部门编号和对应平均薪水。
select deptno,asal2 平均薪水 from (select avg(sal) asal2,deptno from emp group by deptno) where asal2=(select max(asal1) from (select avg(sal) asal1,deptno from emp group by deptno));
3.取得比普通员工(员工代码没有在mgr字段上出现的)的最高薪水还要高的经理人姓名
思路:首先查询emp表中的mgr,再用not in来过滤掉不在mgr列出现的empno后查到对应的工资,再查出这些工资中的最高工资,最后在此emp中把高于此最高工资且职位为经理的员工的相关信息查询显示出来。
--查询方法一:使用nvl select empno,ename,job,sal from emp where sal> (select max(sal) from (select sal from emp where empno not in(select distinct nvl(mgr,0) from emp))) and job='manager'; --查询方法二:使用is not null select empno,ename,job,sal from emp where sal> (select max(sal) from (select sal from emp where empno not in(select distinct mgr from emp where mgr is not null))) and job='manager';
注意:
1)使用not in时要过滤掉子查询中的null值,不然会查询无结果!因为not in等价于!=all,故只要其与子查询中的每个值比较时中有一个为false,整个就为false,而与null值比较时就是false,故整个not in条件就不成立,所以不会返回结果
select empno,ename,sal from emp where empno not in(select distinct mgr from emp) order by empno;
2)使用in的时就不用管null值,因为in在逻辑上等价于any,即只要其中有一个为true,整个就为true,即使与null值比较为false,只要其它子查询的比较为真就可返回相应结果。
select empno,ename,sal from emp where empno in(select distinct mgr from emp) order by empno;
4.取得薪水最高的第六到第十名员工
思路:首先按工资降序查得员工工资信息,再通过子查询获取升序的伪列,再通过子查询更进一步使得伪列可以从6到10进行筛选
select s.* from
(select rownum r,t.* from
(select empno,ename,sal from emp order by sal desc)t)s where r between 6 and 10;--注意where后面是用别名r,不是用关键字rownum,用rownum查不到数据
5.取得每个薪水等级有多少员工
思路:先获取每个员工的薪水等级,以此作为子查询再获取每个薪水等级的员工数
select grade 薪水等级,count(grade) 员工数 from (select empno,ename,sal,grade from emp,salgrade where sal between losal and hisal) group by grade;
6.显示所有员工的姓名,加入公司的年份和月份,按照受雇日期所在月份排序,若月份相同则将受雇年份越早的员工排在越前面
思路:使用to_char获取hiredate数据中的年份和月份,然后进行排序
select ename 员工姓名,to_char(hiredate,'yyyy') 入职年份,to_char(hiredate,'mm') 入职月份 from emp order by 入职月份,入职年份;
推荐阅读
-
Oracle row_number() over()解析函数高效实现分页
-
在Oracle的函数中,返回表类型的语句
-
Oracle 函数大全[字符串函数,数学函数,日期函数]第1/4页
-
Oracle的nvl/nvl2/nullif/coalesce函数介绍
-
Oracle排序、使用nvl函数、使用decode函数、使用case 语法
-
ORACLE逐行累计求和方法(OVER函数)
-
Oracle列转行函数Listagg()查询结果的去重(去除重复值)的方法详解
-
Oracle定义DES加密解密及MD5加密函数示例
-
Oracle to_date()函数的用法介绍
-
编程开发之--Oracle数据库--存储过程和存储函数(2)