ORACLE学习系列三

本学习笔记由本人整理而成,转载请注明出处

———————————————————————————

####【子查询】
###子查询在where子句中
##查找和SCOTT同职位的员工
select a.ename,a.job from emp a where a.job=(select job from emp where name='SCOTT');
##查询薪水比整个机构平均薪水高的员工
select deptno,ename,sal from emp where sal> (select avg(sal) from emp);
##【<>等价于!=】查询出部门中有SALESMAN但职位不是salesman的员工信息
select empno,ename,job,sal,deptno from emp where deptno in (select deptno from emp where job='SALESMAN') and job <> 'SALESMAN';
##【exists】列出有员工的部门信息
select deptno,dname from dept d 
where exists
(select *from emp e 
where d.deptno=e.deptno);

###子查询在having子句中
##查询列出最低薪水高于部门30的最低薪水的部门信息
select deptno,min(sal)from emp group by deptno having min(sal)>(select min(sal) from emp where deptno=30);

###子查询在from子句中
##查询薪水比本部门平均薪水高的员工信息
select e.deptno,e.ename,e.sal from emp e,(select deptno,avg(sal) avgsal from emp group by deptno)x where e.deptno=x.deptno and e.sal>x.avgsal order by e.deptno; 
###子查询在select部分
select e.ename,e.sal,
(select d.deptno from dept d where d.deptno=e.deptno)deptno
from emp e;
——————————————————————————
###【子查询综合示例】
##查询哪个部门的平均工资是最高的,列出部门编码、平均工资
select deptno,avg(sal)from emp group by deptno 
having avg(sal)=(select max(avg(sal)) from emp group by deptno);
##列出各个部门中工资最高的员工信息:名字、部门号、工资
select ename,deptno,sal from emp 
where (deptno,sal)in (select deptno,max(sal) sal from emp group by deptno);
##查询管理者是‘KING’的员工姓名和工资
select ename,sal from emp where mgr=(select empno from emp where ename='KING');
##查询部门所在地(loc)为“NEW YORK”的部门的员工的姓名(ename)、部门名称(dname)和岗位名称(job)
select e.ename,d.dname,e.job from emp e join dept d on e.deptno=d.deptno where d.loc='NEW YORK';
或:
select e.ename,d.dname,e.job from emp e join dept d on e.deptno=d.deptno
where e.deptno=(select deptno from dept where loc='NEW YORK');
##查询工资比公司平均工资高的所有员工的员工号(empno)、姓名(ename)、工资(sal)
select empno,ename,sal from emp where sal>(select avg(sal) from emp);
##查询姓名中包含字母“U”的员工在相同部门的员工的员工号(empno)和姓名(ename)
select empno,ename from emp where deptno in (select deptno from emp where ename like '%U%');
##查询哪些员工的薪水比本部门的平均薪水低
select ename,empno,sal from emp a where sal < (select avg(sal) from emp b where a.deptno=b.deptno)
——————————————————————————
——————————————————————————
####【分页查询】
###【ROWNUM
##返回标识行数据顺序的数字
select rownum,empno,ename,sal from emp;
##利用rownum截取结果集中的部分数据  
select *from (select rownum rn,e.* from emp e) where rn between 8 and 10;
##按薪水倒序排列,取出结果集中第8到第10条的记录
select *from
(select rownum rn,t.* from 
(select empno,ename,sal from emp order by sal desc)t
)
where rn between 8 and 10;
——————————————————————————
###【分页查询综合示例】
##查询emp表前5条记录
select *from emp where rownum <=5;
或:
select *from (select rownum rn,e.* from emp e) where rn between 1 and 5;
##查询第3-5条记录,无需排序
select *from (select rownum rn,e.* from emp e) where rn between 3 and 5;
##查询公司工资最高的三个人
select rownum,ename,sal from(select * from emp order by sal desc) where rownum between 1 and 3 ;
##查询公司工资最低的五个人
select ename,sal from(select rownum rn,e.* from emp e order by sal) where rn between 1 and 5 ;
——————————————————————————
——————————————————————————
####【DECODE函数
##查询职员表,根据职员的职位计算奖励金额,当职位分别是'MANAGER'、'ANALYST'、'SALESMAN'时,奖励金额分别是薪水的1.2倍、1.1倍、1.05倍,如果不是这三个职位,则奖励金额取薪水值
select ename,job,sal,
   DECODE(job,
             'MANAGER',sal*1.2,
             'ANALYST',SAL*1.1,
             'SALESMAN',sal*1.05,
             sal
   )bonus
from emp;
##【case语句】实现类似if-else操作
select ename,job,sal,
   case job when 'MANAGER' then sal*1.2
                 when 'ANALYST' then SAL*1.1
                 when 'SALESMAN' then sal*1.05
                 else sal end
   bonus
from emp;
##【decode函数在分组查询中的应用】计算职位的人数,analyst/manager属于VIP,其余是普通员工operation
select decode(job,'ANALYST','VIP','MANAGER','VIP','OPERATION')job,count(1)job_cnt
from emp group by decode(job,'ANALYST','VIP','MANAGER','VIP','OPERATION')
##dept表中按‘OPERATION’、'ACCOUNTING'、'SALES'排序
select *from dept order by decode (dname,'OPERATION',1,'ACCOUNTING',2,'SALES',3);
——————————————————————————
——————————————————————————
####【排序函数
###【row_number】row_number()over(partition by col1 order by col2)根据col1分组,在分组内部根据col2排序
##按照部门编码分组显示,每组内按职员编码排序,并赋予组内编码
select deptno,ename,empno,row_number()over(partition by deptno order by empno) emp_id from emp;
###【rank】rank()over(partition by col1 order by col2)根据col1分组,在分组内部根据col2给予等级标识,及排名,跳跃排序,如果有相同数据,则排名相同,如有并列第2,下一个排序是4,有重复值
##按照部门编码分组,同组内按薪水倒序排序,相同薪水则按奖金数正序排序,并给予组内等级,用rank_id表示
select deptno,ename,sal,comm,rank()over(partition by deptno order by sal desc,comm)rank_id from emp;
###【dense_rank】dense_rank()over(partition by col1 order by col2)根据col1分组,在分组内部根据col2给予等级标识,相同数据返回相同排名,连续排序,如有并列第2,下一个排序是3
##关联emp和dept表,按照部门编码分组,每组内按照员工薪水排序,列出员工的部门名字、姓名和薪水
select d.dname,e.ename,e.sal,dense_rank()over(partition by e.deptno order by e.sal)drank from emp e join dept d on e.deptno=d.deptno;
——————————————————————————
——————————————————————————
####【集合操作】
集合操作符包括union、union all、intersect和minus,合并多个select语句结果,实现集合的并、交、差。
语法:select statement1 union select statement2;

###【union、union all】获取两个或两个以上结果集的并集
union自动去掉合并后的重复记录,对查询结果排序
union all返回两个结果集中的所有行,包括重复的行,对查询结果不排序
##合并职位是'MANAGER'的员工和薪水大于2500的员工集合,查看两种方式的结果差别
select ename,job,sal from emp where job ='MANAGER'
union 
select ename,job,sal from emp WHERE sal>2500;
##求单个部门工资总和
select sum(sal),to_char(deptno) from emp group by to_char(deptno)
union all
select sum(sal),'Total' from emp;

###【intersect】获取两个结果的交集
##显示职位是'MANAGER'的员工和薪水大于2500的员工的交集
select ename,job,sal from emp where job ='MANAGER'
intersect
select ename,job,sal from emp WHERE sal>2500;

###【minus】获取两个结果集的差集:结果集一减去结果集二的结果
##列出职位是'MANAGER'但薪水低于2500的员工记录
select ename,job,sal from emp where job ='MANAGER'
minus
select ename,job,sal from emp WHERE sal>=2500;
——————————————————————————
——————————————————————————
####【高级分组函数】
rollup、cube、grouping sets运算符是group by子句的扩展
group by rollup(a,b,c)
group by cube(a,b,c)
group by grouping sets((a),(b))

###【rollup】
##假设有表test,有a,b,c,d四个列
select a,b,c,sum(d) from test group by rollup(a,b,c);
等价于:
select a,b,c,sum(d) from test group by a,b,c
union all
select a,b sum(d) from test group by a,b
union all
select a sum(d) from test group by a
union all
select null,null,null,sum(d) from test
对rollup的列从右到左以一次少一列的方式进行分组直到所有列都去掉后的分组(即全表分组);
对于n个参数的rollup,有n+1次分组
##求单个部门工资总和
select sum(sal),nvl(to_char(deptno),'Total')from emp group by rollup(nvl(to_char(deptno),'Total'));
等价于:
select sum(sal),to_char(deptno) from emp group by to_char(deptno)
union all
select sum(sal),'Total' from emp;

###【cube】对于n个参数的cube,有2^n次分组
group by cube(a,b,c),首先对(a,b,c)(a,b)(a,c)(a)(b,c)(b)(c)最后对全表进行group by操作,一共是2^3=8次分组。
###【grouping sets】
##只列出感兴趣的数据
select year_id,month_id,sum(sales_value)
from sales_tab
group by grouping sets((year_id),(month_id))
order by 1,2;
——————————————————————————
——————————————————————————
###【高级查询综合示例】
##创建sales_tab,该表存储了2010-2011年每月每天的销售额
create table sales_tab(
year_id number not null,
month_id number not null,
day_id number not null,
sales_value number(10,2) not null
);
##向sales_tab表中插入测试数据
insert into sales_tab
select trunc(dbms_random.value(2010,2012))year_id,
trunc(dbms_random.value(1,13))month_id,
trunc(dbms_random.value(1,32))day_id,
round(dbms_random.value(1,100),2)sales_value
from dual
connect by level<=1000;
##统计2010-2011年每月每日的销售额,要求使用rollup
select year_id,month_id,day_id,sum(sales_value) from sales_tab 
group by rollup(year_id,month_id,day_id) order by year_id,month_id,day_id;
##统计年月的销售额,要求使用cube函数来完成
select year_id,month_id,sum(sales_value) from sales_tab 
group by cube(year_id,month_id) order by year_id,month_id;
##统计年月的销售额,要求使用grouping sets函数来完成
select year_id,month_id,sum(sales_value) from sales_tab 
group by grouping sets((year_id),(month_id)) order by 1,2;
——————————————————————————
——————————————————————————、
###【实例】
##sales部门有哪些职位
select distinct job from emp where deptno=(SELECT DEPTNO FROM DEPT where dname='SALES');
##哪些人不是别人的经理
select *from emp where empno not in (select distinct mgr from emp where mgr is not null);
或:
select distinct b.* from emp a right join emp b on a.mgr=b.empno where a.mgr is null;
##谁的薪水比FORD高?如果有多个同名,比任何一个叫FORD的人高就行
select distinct ename from emp where sal> (select sal from emp where ename='FORM');
##谁和FORD同部门?列出除了FORD之外的员工名字
select ename from emp where deptno=(select deptno from emp where ename='FORM') AND ename !='FORM';
##哪个部门的人数比部门20的人数多
select deptno from emp group by deptno 
having count(ename)>(select count(ename) from emp where deptno=20);
##列出员工名字和职位,查询员工所在的部门平均薪水大于2000元的员工信息
select ename,job,sal from emp where deptno in
(select deptno from emp group by deptno having avg(sal)>2000);

##where子句中为什么不能写rownum
rownum其实也就是编号,是对查询后的记录做编号操作
伪列:该列并不存在于要查询的表中,该字段的取值取决于查表后的记录数
rownum是在查询数据后,才会有的伪列
##按新闻时间倒序排列,即最新的排在最前面,每页输出5条,查询第二页
select id,title,content,occurtime,num from 
(
  select id,title,content,occurtime,rownum num from 
  (
    select id,title,content,occurtime from news order by occurtime desc
  )where num<=10
)
where num>=6;

猜你喜欢

转载自blog.csdn.net/weixin_41038867/article/details/81744697