组函数基于多行数据返回单个值。
常用组函数:avg()平均值,min(),max(),sum()某列值的和,count()行数,variance()方差,stddev()标准差。
组函数仅在选择列表和having子句中有效。
variance([distinct|all]x)x列方差,distinct只对不同值计算,默认all。标准差计算同理。
group by,按照某些相同的值去进行分组操作。如,
--求每个部门平均薪水
select avg(sal) from emp group by deptno;
--求平均薪水大于2000的部门
select avg(sal),deptno from emp group by deptno having avg(sal)>200;
//注意:group by分组时,可指定一个或多个列,但当使用group by之后,选择列表中只能包含组函数的值或group by的普通字段。
如 select deptno可以查,avg(sal)可以查,ename不可以查 from emp group by deptno having avg(sal)>2000;因为ename既不是组函数计算值,也不是group by字段。
max和min适用于任何字段,sum,avg只用于数值
select min(hiredate),max(sal) from emp;
--组函数除了count(*)外,都跳过空值,而处理非空值。
count一般用来获取记录条数,获取条数可以用*,某一列名或纯数字,从运行效率来看,建议使用数字或某一列值,而不用*。 count(1),count(ename),优于count(*)
组函数不能处理null空值。如select avg(comm) from emp;当comm为null时出错。
此时应该使用nvl函数,迫使组函数包含空值:
select avg(nvl(comm,0))from emp;将空值null变为0来处理。
group by子句,可以包含一个或多个列。
除组函数语句外,select 语句中的每个列都必须在group by子句中给出。如果分组列中具有null值,则null将作为一个分组返回。如果有多行null值,他们将分为一组。
group by子句必须出现在where子句之后,order by子句之前。
where过滤行,having过滤分组。
having支持所有where操作符。
一般在使用group by子句时,应该也给出order by子句。
语法: select —— from —— where —— group by—— having —— order by——
使用group by子句将表分成小组。
结果集隐式按降序配列,如需改变排序可使用order by。
所有出现在select列表中的字段,如果出现的位置不在组函数中,那么必须出现在group by子句中。
select deptno,avg(sal)from emp group by deptno;
不能在where子句中使用组函数,不能在where子句中限制组,使用having来对分组进行限制。
select avg(sal) from emp group by deptno having avg(sal)>1000;
--求部门下雇员的工资>2000的人数
select deptno,count(10)from emp where sal>2000 group by deptno;
--求部门薪水最高
select deptno,max(sal) from emp group by deptno;
--求部门薪资大于1200的平均薪资,按照平均工资降序;
select avg(sal),deptno from emp group by deptno having avg(sal)>1200 order avg(sal);
--部门中工龄最大和工龄最小的人,带员工姓名。
select ename,deptno from emp where
hiredate in (select min(hiredate) from emp group by deptno) or
hiredate in (select max(hiredate) from emp group by deptno);
改进:使用查询连接或者关联查询
select mm2.deptno,e1.ename,e1.hiredate from
emp e1,(select min(e.hiredate) mind,max(e,hiredate) maxd,e.deptno frmo emp e group by e.deptno) mm2
where (e1.hiredate = mm2.mind or e1.hiredate = mm2.maxd) and e1.deptno = mm2.deptno;