目录
常用函数
说明:
AVG([distinct|all] XXX):意思是计算XXX的平均值
SUM([distinct|all] XXX):意思是计算XXX的总计值
MAX([distinct|all] XXX):意思是计算XXX的最大值
MIN([distinct|all] XXX):意思是计算XXX的最小值
COUNT(*[distinct|all] XXX):意思是计算表中数据的总数
使用组函数的时候,空值被自动忽略count(*)除外,但是可以用nvl和nvl2进行空值转换
测试
先查看emp表中的数据
SQL> show user; |
AVG平均值
计算员工的平均工资、平均奖金
SQL> select avg(sal) 平均工资,avg(comm) 平均奖金 from emp; |
由于comm中含有null因此计算的结果只有四个人的平均工资
SUM总计值
计算员工的总工资、总奖金
SQL> select sum(sal) 总工资,sum(comm) 总奖金 from emp; |
同样的,这个总奖金依然是四个人的总奖金,因为null不能和任何值做比较和运算
MAX最大值
计算员工的最高工资,最高奖金
SQL> select max(sal) 最高工资,max(comm) 最高奖金 from emp; |
MIN最小值
计算员工的最低工资、最低奖金
SQL> select min(sal) 最低工资,min(comm) 最低奖金 from emp; |
由此可见在AVG、SUM、MAX、MIN中null是不参与运算的,也就是说被忽略了。
COUNT(*)总数
计算部门总数、员工总数、和有奖金的人数。
SQL> select count(distinct deptno) 部门总数,count(deptno) "部门总数?",count(empno) 员工总数 from emp; |
由此可见,在使用count(XXX) 的时候不能去掉重复值
那么count(*)呢
SQL> select count(empno) a,count(*) b,count(9999) c,count('XXX') d,count(comm) e,count(COMM) f,count('comm') g,count('COMM') h from emp; |
由此可见count('XX')单引号中的值都被当成了任意值,也就是说被当成了count(*)。
SQL> select count("comm") i,count("COMM") j from emp; |
为啥报错?
SQL中只支持单引号,表示字符串常量
SQL中的双引号用于表示字符串
NVL空值转换
按照总人数计算平均奖金
SQL> select count(nvl(comm,0)) 总人数,sum(nvl(comm,0)) 总奖金,avg(nvl(comm,0)) 总人数平均奖金 from emp; |
nvl(comm,0)的意思是将comm中的null转换成0,也可以改成其他值,需要根据实际情况来定。
GROUP BY创建数据组
用于结合聚合函数,根据一个或多个列对结果集进行分组
直接看例子
计算各个部门的总工资,总人数,平均工资。
SQL> select deptno 部门编号,sum(sal) 总工资,count(empno) 总人数, avg(sal) 平均工资 from emp group by deptno; |
结果按照部门编号进行分别运算。
select 之后,from 之前出现的字段,要么是被用于组函数,要么是被用于分组(即用在group by 后面,不过也可以在 select 后不出现)
group by 子句用于 where 条件之后,即可以在分组之前将不合条件的数据过滤掉
group by 在 where 之后,select 之前被编译,所以不能在 group by 中使用列的别名 Oracle 9i 中,分组之后的结果(默认)会按照用于分组的字段进行升序排列;但是 Oracle 10g 中不会进行此排序,需要特别指定才可以
也可以用多列进行分组
计算各部门,各岗位的总工资,总人数和平均工资
SQL> select deptno 部门编号,job 岗位,sum(sal) 总工资,count(empno) 总人数, avg(sal) 平均工资 from emp group by deptno,job; |
ORDER BY排序
如果觉得上述计算结果比较杂乱的话可以使用order by对其进行排序,默认升序
将刚才的结果按照部门编号升序排序
SQL> select deptno 部门编号,job 岗位,sum(sal) 总工资,count(empno) 总人数, avg(sal) 平均工资 from emp group by deptno,job order by 部门编号; |
也可以根据多个分组进行排序
将上述结果不仅按照部门编号升序排,还要按照总工资将序排列(降序使用desc)
SQL> select deptno 部门编号,job 岗位,sum(sal) 总工资,count(empno) 总人数, avg(sal) from emp group by deptno,job order by 部门编号,总工资 desc; |
HAVING子句
对分组后的数据进行筛选
where子句用于分组前的筛选
计算部门编号小于30号的部门、员工总工资、总人数、平均工资
使用where子句在分组前进行筛选
SQL> select deptno 部门编号,sum(sal) 总工资,count(empno) 总人数, avg(sal) 平均工资 from emp where deptno<30 group by deptno; |
使用having子句在分组后进行筛选
SQL> select deptno 部门编号,sum(sal) 总工资,count(empno) 总人数, avg(sal) 平均工资 from emp group by deptno having deptno <30; |
当然也可以在同时使用where和having子句分别对分组前及分组后的结果进行分别筛选
计算部门编号小于30且总工资小于10000的部门、员工总工资、总人数、平均工资
SQL> select deptno 部门编号,sum(sal) 总工资,count(empno) 总人数, avg(sal) 平均工资 from emp where deptno<30 group by deptno having 总工资<10000; |
报错了…原来分组的别名不能用在having子句中
SQL> select deptno 部门编号,sum(sal) 总工资,count(empno) 总人数, avg(sal) 平均工资 from emp where deptno<30 group by deptno having sum(sal)<10000; |
这样就没有问题了。
当然如果在where子句中使用 sum(sal)<10000的话就会报错了,因为where子句中不能使用分组函数。
SQL> select deptno 部门编号,sum(sal) 总工资,count(empno) 总人数, avg(sal) 平均工资 from emp where sum(sal)<10000 group by deptno having sum(sal)<10000; |
SQL语句的编译顺序
from>where>group by>having>select>order by
函数嵌套
求出平均工资
SQL> select dname from dept where deptno= ( select deptno from (select deptno,avg(sal) msal from emp group by deptno) where msal=( select max(avg(sal)) from emp group by deptno ) ); |
最大的部门名称
也可以用rownum来查询
SQL> select a.dname from dept a,( select * from (select avg(sal) s, deptno from emp group by deptno order by avg(sal) desc) where rownum = 1) b where a.deptno = b.deptno; |
特例
having子句可以写在group by之后,也可以写在group by之前
SQL> select deptno,sum(sal),count(*),avg(sal) from emp having avg(sal)<2500 group by deptno; |