在之前学过一个count()函数,此函数的功能可以统计出表中的数据量,实际上这个就是一个统计函数,而常用的统计函数有如下几个:
1.count():查询表中的数据记录
例1.查询emp表中的总记录
Sql>select count(*) from emp;
2.avg():求出平均值
例2.统计出公司的平均工资
Sql>select avg(sal) from emp;
3.sum():求和;
例3.统计出公司的总工资。
Sql>Select sum(sal) from emp;
4.max():求出最大值
例4.查询出emp表中工资最高的员工
Sql >Select ename,max(sal) from emp;
5.min():求出最小值
例5. 查询出emp表中工资最低的员工
Sql>Select ename,min(sal) from emp;
6.group by:分组统计
当数据重复的时候分组才有意义,因为一个人也可以一组,而如果想要使用group by子句完成,此时的SQL语法如下:
Select [distinct] *|分组字段1[别名][.分组字段2[.别名],….]|统计函数
From 表名称 [别名],[表名称[别名,….]]
[where 条件(s)][group by 分组字段1[,分组字段2,…]][order by 排序字段 ASC|DESC[,排序字段ASC|DESC]];
例6:按照部门编号分组,求出每个部门的人数,平均工资
Sql>Select deptno,count (empno),AVG(sal) from emp group by deptno;
例7.按照职位分组,求出每个职位的最高和最低工资
Sql>Select job,max(sal),min(sal) from emp group by job;
例8:统计出领取奖金和不领取奖金的雇员人数及平均工资
Sql>Select comm,count(empno),avg(sal) from emp group by comm;
注意:出现分组后,语法上就有一定的限制,对于分组有以下的限制:
》分组函数可以在没有分组的时候单独使用,可是却不能出现其他的查询字段。
分组函数的单独使用 |
Select count(empno) from emp; |
错误的使用,出现了其他的字符; |
Select empno,count(empno) from emp; |
如果现在要进行分组的话,则select子句之后,只能出现分组的字段和统计函数,其他的字段不能出现:
正确的做法 |
Select job,count(empno),avg(sal) from emp group by job; |
错误的做法 |
Select deptno,job,count(empno),AVG(sal) from emp group by job; |
分组函数允许嵌套,但是嵌套之后的分组函数的查询之中不能再出现任何的字段。
例9:按照职位分组,统计平均工资最高的职位
Sql>Select job,avg(sal ) from emp group by job;
例10:查询出每个部门的名称、位置、部门的人数、平均工资
*确定所需要的数据表:
dept表:每个部门的名称;
emp表:统计出部门的人数平均工资;
*确定已知的关联字段:emp.deptno=dept.deptno;
首先:将dept表和emp表的数据关联
Sql>Select d.dname,e.empno,e.sal from dept d,emp e where d.deptno=e.deptno;
结果显示:
此时的查询结果中,可以发现dname字段上显示出了重复的数据,按照之前对分组的理解,只要数据重复了,那么就有可能进行分组的查询操作,但是此时与之前的分组不太一样,之前的分组是针对于一张实体表进行的分组(emp dept 都属于实体表),但是对于以上的数据是通过查询结果显示的,所以是一张临时的虚拟表,但是不管是否是实体表还是虚拟表,只要是由重复,那么就直接进行分组。
Select d.dname,count(e.ename),avg(e.sal) from dept d,emp e where d.deptno=e.deptno group by d.dname;
但是这个分组并不合适,因为部门一共有四个部门(因为引入了dept表,dept表存在了四个部门的信息),所以应该通过左右连接改变查询的结果。
Select d.dname,count(e.ename),nvl(avg(e.sal),0) from dept d,emp e where d.deptno=e.deptno(+) group by d.dname;
例11:查询出每个部门的编号、名称、位置、部门的人数、平均工资
*确定所需要的数据表:
》dept表:每个部门的编号、名称、位置;
》emp表:统计出部门的人数平均工资;
*确定已知的关联字段:emp.deptno=dept.deptno;
》将emp和dept表关联查询
Select d.deptno,d.dname,d.loc,e.empno,nvl(e.sal,0) from dept d,emp e where d.deptno=e.deptno(+);
结果显示:
此时存在重复数据,而且这个重复的数据平均在了三列上(deptno,dname,loc),所以在分组上的group by 子句中就可以写上三个字段:
Sql>Select d.deptno,d.dname,d.loc,count(e.empno),avg(nvl(e.sal,0)) from dept d,emp e where d.deptno=e.deptno(+) group by d.deptno,d.dname,d.loc;
7.having:再次过滤子句
SQL语言中where和having有什么区别?
select ··· from ··· where ···(只能对分组前的属性进行筛选)
group by ··· having ···(只能对分组后的每个组的整体属性进行筛选,用聚合函数体现) ···· --不使用group by就默认表的整体为一组
Select [distinct] *|分组字段1[别名][.分组字段2[.别名],….]|统计函数
From 表名称 [别名],[表名称[别名,….]]
[where 条件(s)][group by 分组字段1[,分组字段2,…]]
[having 分组后的过滤条件(可以使用统计函数)]
[order by 排序字段 ASC|DESC[,排序字段ASC|DESC]];
例12:查询部门详细信息按部门名、号和部门位置进行分组且部门的平均工资大于2000;
Sql>Select d.deptno,d.dname,d.loc,count(e.empno),avg(nvl(e.sal,0)) from dept d,emp e where d.deptno=e.deptno(+) group by d.deptno,d.dname,d.loc having avg(sal)>2000;
注意:where和having的区别
where:是在执行group by 操作之前进行的过滤,表示从全部数据之中筛选出部分的数据,在where之中不能使用统计函数;
having:是在group by 分组之后的再次过滤,可以在having子句中使用统计函数;
例13:显示非销售人员工作名称以及从事同一工作雇员的月工资的总和,并且要满足从事同一工作的雇员的月工资合计大于¥5000,输出结果按月工资的合计升序排列;
Sql>Select job ,sum(SAL) from emp where job <> ‘SALESMAN’ group by job having sum(SAL)>=5000;
8、Oracle 删除重复数据只留一条
查询及删除重复记录的SQL语句
1、查找表中多余的重复记录,重复记录是根据单个字段(Id)来判断
select * from 表 where Id in (select Id from 表 group byId having count(Id) > 1)
2、删除表中多余的重复记录,重复记录是根据单个字段(Id)来判断,只留有rowid最小的记录
DELETE from 表 WHERE (id) IN ( SELECT id FROM 表 GROUP BY id HAVING COUNT(id) > 1) AND ROWID NOT IN (SELECT MIN(ROWID) FROM 表 GROUP BY id HAVING COUNT(*) > 1);
3、查找表中多余的重复记录(多个字段)
select * from 表 a where (a.Id,a.seq) in(select Id,seq from 表 group by Id,seq having count(*) > 1)
4、删除表中多余的重复记录(多个字段),只留有rowid最小的记录
delete from 表 a where (a.Id,a.seq) in (select Id,seq from 表 group by Id,seq having count(*) > 1) and rowid not in (select min(rowid) from 表 group by Id,seq having count(*)>1)
5、查找表中多余的重复记录(多个字段),不包含rowid最小的记录
select * from 表 a where (a.Id,a.seq) in (select Id,seq from 表 group by Id,seq having count(*) > 1) and rowid not in (select min(rowid) from 表 group by Id,seq having count(*)>1)