一、统计函数
统计函数包括:
COUNT():统计个数
SUM():计算求和
MIN():求最小值
AVG():求平均值
MAX():求最大值
范例:计算emp表中的总人数、平均工资、总工资、最低工资与最高工资
SELECT COUNT(*) 人数, AVG(sal) 平均工资, SUM(sal) 每月总支出,MIN(sal) 最低工资,MAX(sal) 最高工资 FROM emp;
范例:统计出公司的平均雇佣年限
SELECT AVG(MONTHS_BETWEEN(SYSDATE,hiredate)/12)
FROM emp; ---统计函数允许与其他的函数嵌套
注意:以上的几个操作函数,在表中没有数据的时候,只有COUNT()函数会返回结果,其他都是null。
二、分组统计
如果要进行分组则应该使用GROUP BY句子完成,那么此时的SQL语法结构变为如下形式:
【4选出所需要的数据列】SELECT [DISTINCT] * | 分组列[别名],分组列 [别名]…
【1确定数据来源】FROM 表名
【2筛选数据行】[WHERE 限定条件(s)];称[别名]
【3对筛选的行分组】[GROUP BY 分组字段,分组字段…]
【5数据排序】ORDER BY 排序字段 [ASC|DESC],排序字段 [ASC|DESC], …
范例:根据部门编号分组,查询出每个部门的编号、人数、平均工资
SELECT deptno, COUNT(*), AVG(sal)
FROM emp
GROUP BY deptno;
使用分组需要注意三个条件:
1、如果查询不使用GROUP BY 子句,那么SELECT 子句中只允许出现统计函数,其他任何字段不允许出现。
2、如果查询中使用了GROUP BY 子句,那么SELECT子句中只允许出现分组字段、统计函数、其他字段都不允许出现。
3、统计函数允许嵌套,但是嵌套之后的SELECT子句里面只允许出现嵌套函数,而不允许出现任何字段,包括分组字段。
三、HAVING 子句
HAVING 子句:有HAVING时必然有GROUP BY。反之未必。
【5选出所需要的数据列】SELECT [DISTINCT] * | 分组列[别名],分组列 [别名]…
【1确定数据来源】FROM 表名称[别名]
【2筛选数据行】[WHERE 限定条件(s)];
【3对筛选的行分组】[GROUP BY 分组字段,分组字段…]
【4 针对于筛选的行分组】[HAVING 分组过滤]
【6数据排序】ORDER BY 排序字段 [ASC|DESC],排序字段 [ASC|DESC], …
范例:要求查询出每个职位的名称,职位的平均工资,但是要求显示的平均工资高于2000。
SELECT job, AVG(sal)
FROM emp
GROUP BY job
HAVING AVG(sal) > 2000;
说明:关于WHERE与HAVING的区别?
WHERE子句是在GROUP BY 分组之前进行筛选,指的是选出那些可以参与分组的数据,并且WHERE子句中不允许使用统计函数;
HAVING子句实在GROUP BY分组之后执行的,可以使用统计函数
四、子查询嵌套
子查询就是查询嵌套。都需要使用()。而且查询子句的一个任意位置上都可以随意出现子查询。但是出现子查询最多的位置:WHERE, FROM,HAVING 。如下使用推荐方案。
WHERE子句:子查询返回单行单列、单行多列、多行单列;
HAVING子句:子查询返回单行单列,而且要使用统计函数过滤;
FROM子句:子查询返回的是多行多列;
1、where子句:
where子句中主要返回单行单列、单行多列、多行单列等几种情况:
范例:要求查询出工资工资最低的固原信息。
SELECT *
FROM emp
WHERE sal=(SELECT MIN(sal) FROM emp);
对于where子句查询返回多行单列的情况,那么实质上就相当于告诉用户一个数据的操作范围。而对范围的判断,主要有三个运算符:IN 、ANY 、ALL
IN 操作:
范例:找出工资在MANAGER职员范围内的雇员信息
SELECT *
FROM emp
WHERE sal IN(SELECT sal FROM emp WHERE job = 'MANAGER');
NOT IN操作:
范例:找出工资不在MANAGER职员范围内的雇员信息
SELECT *
FROM emp
WHERE sal IN(SELECT sal FROM emp WHERE job = 'MANAGER');
注意,这里的操作,一定要保证子句里查询的结果不为null。
ANY操作:
1、=ANY: 功能上与IN完全没有任何区别
SELECT *
FROM emp
WHERE sal = ANY (SELECT sal FROM emp WHERE job = 'MANAGER');
2、>ANY: 比子查询返回的最小的内容要大
SELECT *
FROM emp
WHERE sal > ANY (SELECT sal FROM emp WHERE job = 'MANAGER');
3、<ANY: 比查询返回的最大值的内容要小
SELECT *
FROM emp
WHERE sal < ANY (SELECT sal FROM emp WHERE job = 'MANAGER');
ALL操作:
1、>ALL: 比子查询返回最大的值要大
SELECT *
FROM emp
WHERE sal > All (SELECT sal FROM emp WHERE job = 'MANAGER');
2、<ALL: 比子查询返回的最小的值还要小
SELECT *
FROM emp
WHERE sal < All (SELECT sal FROM emp WHERE job = 'MANAGER');
Exists()判断是否满足条件
如果现在子查询有数据返回(不管任何数据)就表示条件满足。那么就显示出数据,否则不显示。
使用exists()只关心子查询里面返回的是否有行,至于什么行,它不关心
SELECT *
FROM EMP
WHERE EXISTS( SELECT * FROM emp WHERE empno=7839);
2、having 子句使用子查询
使用HAVING的前提是得使用了GROUP BY,而使用了GROUP BY就一定要分组。
范例:要求统计出所有高于公司平均工资的部门编号、平均工资、部门人数。
SELECT deptno, COUNT(*),AVG(sal)
FROM emp
GROUP BY deptno
HAVING AVG(sal) > (SELECT AVG(sal) FROM emp);
3、from子句使用子查询
范例:将这个语句查询出来的表最为一张临时表:SELECT deptno, COUNT(empno) count, AVG(sal) avg FROM emp GROUP BY deptno---根据部门进行分组查询出部门人数、平均工资等信息。
然后将temp这张表与dept这张表进行多表查询。
SELECT d.deptno, d.dname, d.loc, temp.count, temp.avg
FROM dept d, ( SELECT deptno, COUNT(empno) count, AVG(sal) avg
FROM emp GROUP BY deptno ) temp
WHERE d.deptno = temp.deptno(+);