1.host cls清除SQL plus上的文字。
2.使用avg()平均数 sum()总和。
select avg(sal),sum(sal) from emp;--求工资的平均数和总和。
3.max()最大值,min()最小值
select max(sal),min(sal) from emp;--求工资的最大值和最小值。
4.count()总的记录数
select count(deptno) from emp;--求emp表的总记录数。
select count(distinct deptno) from emp;--去除empno的重复查出总记录数。
5.vw_concat()行转列
select deptno 部门号,wm_concat(empno)姓名 from emp group by deptno;--通过部门编号进行分组行转列查询
6.nvl(?,?)如果第一个为null ,结果就是第二个,否则就是第一个
select sum(comm)/count(*) 一,sum(comm)/count(comm) 二,avg(comm) 三 from emp;
--三种方式求奖金的平均数 (第一种分母为14)(其他的都是4)
结果: 一 二 三
---------- ---------- ----------
157.142857 550 550
select sum(comm)/count(*) 一,sum(comm)/count(nvl(comm,0)) 二,avg(comm) 三 from emp;
结果: 一 二 三
---------- ---------- ----------
157.142857 157.142857 550
7.group by 分组查询
在select 列表中所有未包含在组函数中的列都应该包含在group by子句中
select a,b,c,组函数(x) from 表名 group by a,b,c;
--通过部门进行分组,求平均薪水--
select deptno,avg(sal) from emp group by deptno
--通过部门号排序,通过部门,工作分组查询总工资
select deptno,job,sum(sal) from emp group by deptno,job order by deptno;
--通过部门分组查询部门的平均工资过滤平均工资小于200的部门---
select deptno,avg(sal) from emp group by deptno having avg(sal)>2000
8.having和where的区别
having用于分组函数,where不能用于分组函数,某些情况下作用是一样的
select deptno,avg(sal) from emp having deptno=10 group by deptno;
select deptno,avg(sal) from emp where deptno=10 group by deptno;
where条件不能有分组函数
例:select deptno,avg(sal) from emp where avg(sal)>2000 group by deptno;
sql优化尽量使用where因为where的效率更高where先过滤后分组。比如员工表共有1亿条数据要查询编号为10的员工(共10 人)where先过滤出这10个人然后进行分组,having先分组,在过滤。
9.group by 增强
group by rollup(a,b)= group by rollup a,b+group by a+group by null;
select deptno,job,sum(sal) from emp group by rollup(deptno,job);
10.内连接,左连接,右连接,笛卡尔乘积
------内连接查询-------
select a.*,b.* from emp a inner join dept b on a.deptno=b.deptno;
------左连接------
select a.*,b.* from emp a left outer join dept b on a.deptno=b.deptno;
------右连接------
select a.*,b.* from emp a right join dept b on a.deptno=b.deptno;
笛卡尔乘积
select a.*,b.* from emp a,dept b;
11. --自链接查询 老板编号等于员工编号 不适合操作大表,笛卡尔乘积太大---
select e.ename 员工姓名,b.ename 老板姓名 from emp e,emp b where e.mgr=b.empno;
--层次查询--connect by相当于where prior上一层的 start whit empno=7839 --就相当于start with mgr is null--
select level,empno,ename,sal,mgr
from emp
connect by prior empno=mgr start with mgr is null
order by level;
12.--子查询:一个select嵌套一个select--
select * from emp where sal>(select sal from emp where ename='SCOTT');--可以使用子查询的位置--where,select,having,from--
--SELECT 后面的子查询只能是单行子查询(结果只有一行)
select empno,ename,sal,(select job from emp where empno=7369) 第四列 from emp;
--having--查询部门平均薪资大于30号部门的最大工资的部门和平均薪资--
select deptno,avg(sal) from emp group by deptno having avg(sal)>=(select max(sal) from emp where deptno=30)
--from--
select * from (select empno,ename from emp);
--主查询和子查询不在同一张表中--只要子查询的结果可以用于主查询就没问题
select * from emp where deptno=(select deptno from dept where dname='SALES')
--另一种方法,多表查询--
select e.* from emp e,dept d where e.deptno=d.deptno and d.dname='SALES';
--子查询,排序--rownum只能用<= 不能用>=--
--通过薪资降序--取前三行
select rownum,empno,sal from (select * from emp order by sal desc)where rownum<4
--相关子查询--找出员工表中员工工资大于部门平均薪资的员工--
select empno,ename,sal,(select avg(sal) from emp where deptno=e.deptno) 部门平均薪资
from emp e where
sal>(select avg(sal) from emp where deptno=e.deptno)
--单行子查询--查询员工信息,职位与7566员工一样,薪水大于7782.
select *
from emp
where job=(select job from emp where empno=7566) and
sal>(select sal from emp where empno=7782);
--查询工资最低的员工信息--
select *
from emp
where sal=(select min(sal) from emp)
--多行子查询 查询最低工资大于20号部门最低工资的部门号和部门的最低工资
select deptno,min(sal)
from emp group by deptno
having min(sal)>(select min(sal)
from emp
where deptno=20);
--in--查询部门名称是sales和accounting的员工信息
select *
from emp
where deptno in(select deptno from dept where dname='SALES' or dname='ACCOUNTING')
--多表联查--
select e.*
from emp e,dept d
where e.deptno=d.deptno and (d.dname='SALES' or d.dname='ACCOUNTING')
--any--任意一个--查询薪资比30号部门任意一个员工高的员工信息
select *
from emp
where sal > any(select sal from emp where deptno=30)
--单行子查询和多行子查询中有null值的解决办法--
select * from (select * from emp where ename='tom')
--多行子查询有null值--查询不是老板的员工
select * from emp where empno not in (select mgr from emp where mgr is not null)
13.案例1 ,通过薪资降序,分页查找5-8条数据
select rownum, 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>4;
案例2.查找emp 表中员工薪水大于本部门平均薪水的员工--
--相关子查询--
select empno,ename,sal,(select avg(sal)
from emp where deptno=e.deptno) 部门平均薪水,deptno
from emp ewhere sal>(select avg(sal)
from emp
where deptno=e.deptno)
--多表联查--
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.display); 查看运行计划
案例3.查询1980年入职的人数1981年入职的人数1982年入职的人数,1987年入职的人数 这四年入职的总人数total表示。
使用函数解决
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
使用子查询解决
select
(select count(*) from emp) Total,
(select count(*) from emp where to_char(hiredate,'yyyy')='1980') "1980",
(select count(*) from emp where to_char(hiredate,'yyyy')='1981') "1981",
(select count(*) from emp where to_char(hiredate,'yyyy')='1982') "1982",
(select count(*) from emp where to_char(hiredate,'yyyy')='1987') "1987"
from dual;
14.练习
一张学生表 两个字段 id sname
一张选课表 两个字段 主键 sc_id cid关联学生的id
create table student(
id number (9) primary key,
sname varchar2(20)
)
create table sclass(
sc_id number (9)primary key,
cid varchar2(100)
)
显示结果
sql语句
select sc.sc_id,wm_concat(sname)
from student s,sclass sc
where instr(sc.cid,s.id)>0
group by sc.sc_id
解释:instr返回字符或字符串在另一个字符串中第一次出现的位置
wm_concat行转列