欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Oracle作业5——多表查询、子查询

程序员文章站 2022-08-09 11:31:29
一、基础练习: 1.查询和scott相同部门的员工姓名ename和雇用日期hiredate 2.查询在部门的loc为NEW YORK的部门工作的员工的员工姓名ename,部门名称dname和岗位名称job 3.查询上司是king的员工姓名(ename)和工资(sal) 4.查询与姓名中包含字母U的员 ......

一、基础练习:

1.查询和scott相同部门的员工姓名ename和雇用日期hiredate

select ename,hiredate from emp where deptno=(select deptno from emp where ename='scott');

Oracle作业5——多表查询、子查询

2.查询在部门的loc为new york的部门工作的员工的员工姓名ename,部门名称dname和岗位名称job

select e.ename,d.dname,e.job,d.loc from emp e,dept d where e.deptno=d.deptno and d.loc='new york';

Oracle作业5——多表查询、子查询

3.查询上司是king的员工姓名(ename)和工资(sal)

select ename,sal from emp where mgr=(select empno from emp where ename='king');

Oracle作业5——多表查询、子查询

4.查询与姓名中包含字母u的员工在相同部门的员工信息

select * from emp where deptno in(select deptno from emp where ename like '%u%');

Oracle作业5——多表查询、子查询

5.查询所有雇员姓名和部门名称(使用left join,inner join, right join)

select e.ename,d.dname from emp e inner join dept d on e.deptno=d.deptno;
select e.ename,d.dname from emp e left join dept d on e.deptno=d.deptno;
select e.ename,d.dname from dept d right join emp e on e.deptno=d.deptno;

Oracle作业5——多表查询、子查询

6.显示每个员工的员工姓名、部门名称、职务、工资、和工资等级信息(使用left join,inner join, right join)

select e.ename,d.dname,e.job,e.sal,s.grade from emp e inner join dept d on e.deptno=d.deptno inner join salgrade s on e.sal between s.losal and s.hisal;

select e.ename,d.dname,e.job,e.sal,s.grade from emp e left join dept d on e.deptno=d.deptno left join salgrade s on e.sal between s.losal and s.hisal;

select e.ename,d.dname,e.job,e.sal,s.grade from dept d right join emp e on e.deptno=d.deptno right join salgrade s on e.sal between s.losal and s.hisal;

Oracle作业5——多表查询、子查询

二、综合练习

1.取得每个部门最高薪水的人员名称2.列出受雇日期早于其直接上级的所有员工的编号,姓名,部门名称

--使用相关子查询
select empno,ename,sal,deptno from emp e where e.sal=(select max(sal) from emp m where m.deptno=e.deptno) order by deptno;
--使用多表连接查询(渔舟唱晚同学的)
select empno,ename,sal,deptno from emp q, (select e.deptno 部门, max(e.sal) 最高薪资 from emp e group by e.deptno) 
r where r.部门 = q.deptno and q.sal = r.最高薪资 order by q.deptno;
--使用dense_rank()函数结合order by
select * from(select empno,ename,sal,deptno,dense_rank() over(partition by deptno order by sal desc)rn from emp) where rn=1 order by deptno;
--使用in子查询(有bug)
select empno,ename,deptno,sal from emp where sal in(select max(sal) from emp group by deptno) order by deptno;

Oracle作业5——多表查询、子查询

--测试上面的in子查询bug:发现10部门的nullun也显示出来了,但其并非10部门最高工资,10部门最高工资为5000
insert into emp(empno,ename,deptno,sal) values(1015,'nullun',10,3000);
select empno,ename,deptno,sal from emp where sal in(select max(sal) from emp group by deptno) order by deptno;

Oracle作业5——多表查询、子查询

2.列出受雇日期早于其直接上级的所有员工的编号,姓名,部门名称

--左自连接和多表查询
select e.empno 员工编号,e.ename 员工姓名,m.ename 主管姓名,e.hiredate 员工受雇日期, m.hiredate 上级雇用日期,d.dname 部门名称
from emp e,emp m,dept d where m.empno(+)=e.mgr and e.hiredate<m.hiredate and e.deptno=d.deptno order by e.empno;

Oracle作业5——多表查询、子查询

--相关子查询和多表查询
select e.empno,e.ename,d.dname from emp e,dept d where e.hiredate
<(select hiredate from emp m where m.empno=e.mgr) and e.deptno=d.deptno order by e.empno;

Oracle作业5——多表查询、子查询

3.列出所有"clerk"(办事员)的姓名及其部门名称,部门的人数

思路:1.先查询job为clerk的所有部门编号,将该子查询结果命名为a;2.再从emp表查询与a查询中部门编号相同的员工所在的部门人数,这一步的查询结果命名为b;3.最后从emp表、dept表和b查询中进行多表查询获取job为clerk的所有员工的姓名、部门名称和所在部门人数。

select e.ename,d.dname,t.部门人数,e.job from emp e,dept d,(select deptno,count(1) 部门人数 from emp where deptno in(
select distinct deptno from emp where job='clerk') group by deptno)t 
where e.deptno=d.deptno and e.job='clerk' and t.deptno=e.deptno;

Oracle作业5——多表查询、子查询

4.列出与"scott"从事相同工作的所有员工及部门名称

select e.*,d.dname from emp e,dept d where e.job=(select job from emp where ename='scott') and e.deptno=d.deptno;

Oracle作业5——多表查询、子查询

5.查出某个员工的上级主管,并要求出这些主管中的薪水超过3000

select e.empno 员工编号,e.ename 员工姓名,m.ename 主管姓名,m.sal 主管工资 from emp e,emp m where m.empno(+)=e.mgr and m.sal>3000;

Oracle作业5——多表查询、子查询

6.找出部门10中所有经理(manager)和部门20中所有办事员(clerk)的详细资料

select e.*,d.dname,d.loc,s.* from emp e,dept d,salgrade s where e.deptno=d.deptno and e.sal between s.losal and s.hisal 
and (e.deptno=10 and e.job='manager' or e.deptno=20 and e.job='clerk'); --注意:e.deptno=10 and e.job='manager' or e.deptno=20 and e.job='clerk' 要用括号括起来,不然会与前面的and条件混淆造成错误!

Oracle作业5——多表查询、子查询

7.找出早于12年前受雇的员工. 并且按受雇年份倒序排序

思路一:用months_between比较当前系统时间和受雇日期之前相差的月份,然后除以12,如果值大于12,则是早于12前受雇的员工。

--有错误的语句
select e.*,to_char(hiredate,'yyyy') 受雇年份,round((months_between(sysdate,hiredate)/12),2) 受雇年限 from emp e where 受雇年限>12 order by 受雇年份 desc; 
/*为什么“受雇年限”会是无效的标识符呢?因为select语句在where语句后面才执行,而列的别名(受雇年限)是在select时才生成的,故在where子句中看不到这个别名(受雇年限),自然无法引用这个别名了。*/

--排错后的正确语句
select e.*,to_char(hiredate,'yyyy') 受雇年份,round((months_between(sysdate,hiredate)/12),2) 受雇年限 from emp e 
where (months_between(sysdate,hiredate)/12)>12 order by 受雇年份 desc;

Oracle作业5——多表查询、子查询

思路二:用add_months判断,(受雇日期+12*12)得出的日期如果小于当前系统时间,则是早于12前受雇的员工。

select e.*,to_char(hiredate,'yyyy') 受雇年份,add_months(hiredate,12*12) 受雇十二周年日,round((months_between(sysdate,hiredate)/12),2) 受雇年限 from emp e 
where add_months(hiredate,12*12)<sysdate order by 受雇年份 desc;
--注意:离当前日期越远的日期越小,反之,离当前日期越近的日期越大。

Oracle作业5——多表查询、子查询

8.列出从事同一种工作但属于不同部门的员工的一种组合

--不算完美但算比较接近题意的sql语句
select distinct e.empno,e.ename,e.job,e.deptno from emp e,emp p where e.deptno!=p.deptno and e.job=p.job order by job,deptno;
--其它两种不等于的写法
select distinct e.empno,e.ename,e.job,e.deptno from emp e,emp p where e.deptno<>p.deptno and e.job=p.job order by job,deptno;
select distinct e.empno,e.ename,e.job,e.deptno from emp e,emp p where e.deptno^=p.deptno and e.job=p.job order by job,deptno;
/*精妙之处:使用distinct!如果不使用distinct,查询结果会出现很多一样的重复数据!*/

Oracle作业5——多表查询、子查询

分析:为什么说上面的sql语句不算完美呢?因为从上图可看出job为clerk,且deptno=20的记录有两条,即分别是第2和第3条查询记录,这就与题目要求的“从事同一种工作但属于不同部门的员工”不一致了,故最理想的查询结果应该如下:

Oracle作业5——多表查询、子查询    Oracle作业5——多表查询、子查询

9.查询有奖金的所有员工的姓名、奖金以及所在部门名称

--如果奖金等于0也算有奖金,那如下实现:
select ename,comm,dname from emp e,dept d where comm is not null and e.deptno=d.deptno;

Oracle作业5——多表查询、子查询

--如果奖金等于0不算有奖金,则如下实现:
select ename,comm,dname from emp e,dept d where comm is not null and comm<>0 and e.deptno=d.deptno;

Oracle作业5——多表查询、子查询

10.给任职日期超过25年的员工加薪10%

select e.ename,e.sal 原薪水,e.sal*1.1 加薪后薪水,round((months_between(sysdate,hiredate)/12),2) 受雇年限 from emp e 
where (months_between(sysdate,hiredate)/12)>25;

Oracle作业5——多表查询、子查询