Oracle学习第七天

高级查询

1.分组查询
①概念
分组函数作用于一组数据,并对一组数据返回一个值。
②分组函数的使用
分组函数
avg()、sum()、min()、max()、count()
、wm_concat():行转列
select avg(sal),sum(sal)from emp;
select max(sal),min(sal)from emp;
select count(*) from emp;
distinct:去除重复的记录
select count(distinct deptno) from emp;
select deptno,wn_concat(ename) from emp group by deptno;
注:分组函数会自动忽略空值
③使用group by子句数据分组
--求出员工表中各部门的平均工资
select deptno,avg(sal) from emp group by deptno;
--多个分组
select deptno,job,sum(sal) from emp group by deptno,job;
④使用having子句过滤分组结果集
select deptno,avg(sal) from emp group by deptno having avg(sal)>2000
注:不能在where子句中使用组函数
having:先分组 后过滤
where: 先过滤 后分组
⑤在分组查询中使用order by子句
order by 序号/字段
分组函数嵌套
求部门平均工资的最大值
select max(avg(sal)) from emp group by deptno
⑥group by语句的增强
select deptno,job,sum(sal) from emp group by deptno,job
select deptno,sum(sal) from emp group by deptno
select sum(sal) from emp 



select deptno,job,sum(sal) from emp group by rollup(deptno,job)


语法
group by rollup(a,b)
等价于
group by a,b
+
group by a 
+
group by null
⑦sqlplus的报表功能
报表包括:标题、页码、别名等
ttitle col 15 '我的报表' col 35 sql.pno
col deptno heading 部门号
col job heading 职位
col sum(sal) heading 工资总额
break on deptno skip 1
2.多表查询
①概念
多个表中获取数据
②笛卡尔集
列相加 行相乘


为了避免笛卡尔集,可以在where加入有效的连接条件
在实际运行环境下,应避免使用笛卡尔全集

③连接类型
等值连接
连接条件是=号
不等值连接
连接条件是>,>=,<,<=,<>号
外连接
部门统计员工人数,显示部门号,部门名称,人数
select d.deptno,d.dname,count(e.empno)
from emp e, dept d where e.deptno(+)=d.deptno[(+)]
group by d.deptno,d.dname;
注:通过外连接,把对于连接条件不成立的记录,仍然包含在最后的结果中
左外连接:当连接条件不成立的时候,等号左边的表仍然被包含
右外连接:当连接条件不成立的时候,等号右边的表仍然被包含

自连接
--查询员工姓名和员工老板的姓名
注:核心-》通过别名,将同一张表视为多张表
select e.ename 员工姓名,b.ename 老板姓名
from emp e,emp b
where e.mgr=b.empno;
④自连接存在的问题
不适合操作大表-->解决办法:层次查询

⑤层次查询
某些情况下,可以替代自连接
本质上,是一个单表查询


select level(伪列) empno,ename,sal,mgr
from emp 
connect by prior empno=mgr( 上一层的员工号-老板号)
start with empno=7839(遍历起始位置)(根节点表示方式mgr is null)
order by 1;

3.子查询
①作用
解决 不能一步求解的问题
②需要注意的10个问题
子查询语法中的小括号
子查询放入小括号中
子查询的书写风格
可以使用子查询的位置:where,select ,having,from
(select 后面的子查询必须是单行子查询)
不可以使用子查询的位置:group by

强调:from后面的子查询
主查询和子查询可以不是同一张表
一般不在子查询中使用排序 但是在top_N分析问题中,必须对子查询排序
例:找到员工表中工资最高的前三名
注意:行号永远按照默认的顺序生成
行号只能使用<,<=;不能使用>,>=
正确:select rownum,empno,ename,sal from (select * from emp order by sal desc) where rownum<=3
错误:select rownum,empno,ename,sal from emp
where rownum<=3 order by sal desc;
一般先执行子查询,再执行主查询;但相关子查询例外
相关子查询:找到员工表中薪水大于本部门平均薪水的员工
select empno,ename,sal,(select avg(sal) from emp where deptno=e.deptno) avg sal from emp e where sal>(select avg(sal) from emp where deptno=e.deptno);
单个子查询只能使用单行操作符;多行子查询只有使用多行操作符
多行操作符:
in(等于列表中的任何一个)、any(和子查询返回的任意一个值比较)、all(和子查询返回的所有值比较)
select * from emp where sal>any(select sal from emp where deptno=30)等价于
select * from emp where sal>(select min(sal) from emp where deptno=30);

select * from emp where sal>all(select sal from emp where deptno=30)等价于
select * from emp where sal>(select max(sal) from emp where deptno=30);

注意:子查询中是null的问题
看是否是空值用 is null
--查询不是老板的员工
select * from emp where empno not in(select mgr from emp where egr is not null)

4.综合示例
①分页查询显示员工信息:显示员工号,姓名,月薪(每页显示四条记录,显示第二页的员工,按照月薪降序排列)
分页查询:
select r,empno,ename,sal
from (select rownum r,empno,ename,sal
from (select rownum,empno,ename,sal from emp order by sal desc) e1
where rownum<=8) e2
where r>=5;
②找到员工表中薪水大于本部门平均薪水的员工
1.
select empno,ename,sal,(select avg(sal) from emp where deptno=e.deptno) avg sal from emp e where sal>(select avg(sal) from emp where deptno=e.deptno);
2.
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;

生成执行计划 
explain plan for + sql语句
执行生成计划
select * from table(dbms_xplan.dispaly);
③按部门统计员工人数,按照格式输出
select count(*) Total,
sum(decode(to_char(hiredate,'YYYY'),'1980',1,0)) "1980",
sum(decode(to_char(hiredate,'YYYY'),'1981',1,0)) "1981",
sum(decode(to_char(hiredate,'YYYY'),'1982',1,0)) "1982",
sum(decode(to_char(hiredate,'YYYY'),'1987',1,0)) "1987"
from emp;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章