对表数据进行检索时,经常需要对结果进行汇总和计算,对数据查询的结果进行求总和、平均值、最大值、最小值的计算称为统计。
本小节讨论SELECT语句中用于数据统计的函数和子句。
1、聚合函数
集合函数是在查询结果记录的列集上进行各种统计运算,运算的结果形成一条汇总记录。
为了进一步方便用户,增强检索功能,SQL提供了许多统计函数,主要有:SUM、AVG、COUNT、MAX、MIN。
(1) 求和函数SUM与求平均值函数AVG
SUM和AVG是数值型列值的求和与求平均值函数,它们只能用于数值型字段,而且忽略列值为NULL的记录。
语法格式如下:
SUM/AVG([ALL | DISTINCT ] 字段名)
其中,ALL和DISTINCT关键字用于指定求和范围。
ALL表示对所选字段的所有值求和,DISTINCT表示只计算不同值的和。如果有许多重复值,则这些值只计算一次。这里系统默认为ALL设置。表达式通常是一个数值型字段,也可以是由常量、字段(列)、函数或者运算符组成的一个数值型表达式。
练习1:计算01系部开设课程的学分平均值。
练习2:计算李涛老师所授课程的学分总和。
使用聚合函数作为SELECT的选择列时,如果不为其指定列标题,则系统将对该列输出标题“无列名”。
(2)最大值函数MAX与最小值函数MIN
MAX和MIN函数分别用来返回指定列表达式中的最大值和最小值,忽略列值为NULL的记录,列表达式中的列可以是任何可排序的类型。
语法格式如下:
MAX| MIN([ALL | DISTINCT ] 字段名)
其中,ALL和DISTINCT含义同SUM函数。表达式可以是由常数、字段名(列)以及函数构成的表达式,其数据类型可以是数值型、字符串型和日期时间型等。
练习3:找出信息技术类课程中报名人数最多的是多少人
(3) 计数函数COUNT
COUNT函数用于统计查询结果集中满足条件的记录的个数(行数),
其语法格式如下:
COUNT([ [ALL | DISTINCT ] expression ] | *)
语法上,“*”用于统计所有记录的个数(总行数),ALL用于统计指定列的列值非空的记录个数,DISTINCT用于统计指定列的列值非空且不重复的记录个数。默认值为ALL。其中,表达式的数据类型是除了text、ntext、image之外的任何类型。
COUNT函数有以下3种用法。
COUNT(*):返回结果集中的记录总数,包括NULL值和重复值在内。
COUNT(ALL 表达式):返回结果集中的记录总数,不包括NULL值但包括重复值在内。
COUNT(DISTINCT 表达式):返回结果集中的记录总数,不包括NULL值和重复值在内。
练习4:求学生的总人数。
练习5:求报名人数在30以上的课程有多少门
练习6:求选修了课程的学生的总人数
统计函数的作用范围既可以是一个表中的全部记录,也可以是由WHERE子句指定的该表的一个子集。在前面的示例中,都是针对表中的全部记录或由WHERE子句指定的该表的一个子集进行计算的。统计函数还可以作用于表中的一组或多组记录,此时将针对每组记录产生一个单值。组的划分将由下面要介绍的GROUP BY子句来实现。
数据分组统计(见课本94页)
格式:group by 字段名列表
[having 条件]
Group by
Group by 列名 having 条件
Group by all 列名
Compute函数
Compute 函数 by 列名
(1)GROUP BY 子句
在大多数情况下使用统计(聚合)函数,返回的是所有行数据的统计结果。如果需要按某一字段(分类的依据)数据的值进行分类,在分类的基础上再分别进行统计计算,就需要使用GROUP BY子句了。数据分组是指通过GROUP BY 子句按一定的条件对查询到的结果进行分组,再对每一组数据统计计算 ,形成汇总行。
GROUP BY子句的语法格式如下:
SELECT 列名称(必须出现在group by子句),聚合函数
FROM 表名称
WHERE 条件表达式
ORDER BY 列名称
GROUP BY 列名称[, ... n ]
[HAVING 条件表达式]
例11:计算各系部开设课程的限选人数的平均值,只显示人数大于12的
练习1:查看学生表中各专业共有几个班
练习2:求数据库中各班级的学生数
练习3:求各系部开设课程的平均学分和可以报名的总人数。
练习4:各个学生分别选修了几门课
注意:在GROUP BY子句中,字段别名不能作为分组表达式来使用。SELECT后面每一列数据除了出现在统计函数中的列以外,都必须在GROUP BY子句中应用。
GROUP BY ALL 列名称 作用是:除了被统计的列会输出,而不满足条件(where)的组也会有列值输出,而不会进行计算。
(2) HAVING子句
当完成数据结果的查询和统计后,可以使用HAVING子句(条件表达式通常是由聚合函数组成)来对查询和统计的结果进行进一步的筛选,通常和GROUP BY子句一起使用,其行为与WHERE子句相似,只是WHERE子句作用于表的单个行(作用对象是原表数据)而言,HAVING子句对生成的组进行筛选。
*在执行查询时,要按照GROUP BY 子句分组之前先去掉不满足WHERE条件的行,而HAVING 子句中的条件在分组之后被应用。
注意:在SELECT语句中,当WHERE、GROUP BY、HAVING子句都被使用时,要注意它们的作用和执行顺序:WHERE用于筛选由FROM指定的数据对象,GROUP BY用于对WHERE的结果进行分组,HAVING则是对GROUP BY以后的分组统计后的数据进行过滤。
例12:查看限选人数小于等于10的各系部的总报名人数大于100的课程的平均学分和报名总人数
练习5:在找出选课人数大于2人的各门课程课程号及选修人数
(3)用COMPUTE子句汇总数据
有时我们不仅需要知道数据的汇总情况,可能还需要知道详细的数据记录,此时可以使用
COMPUTE(统计)或COMPUTE BY子句(分组统计)生成明细以及汇总结果。COMPUTE子句用于对列进行聚合函数计算并生成汇总值,汇总的结果以附加行的形式出现
使用COMPUTE子句,允许同时浏览查询所得的各字段数据的细节以及统计各字段数据所产生的总和。它既可以计算数据分类后的和,又可以计算所有数据的总和。
Compute 聚合函数 :相当于使用select 聚合函数进行数据统计并且显示明细
Compute 聚合函数[,…n] by 列名称:相当于select 聚合函数+group by 列名称进行分组统计并且显示明细
COMPUTE子句的语法格式为
COMPUTE 集合函数名(expression)[, ...n ][ BY expression [, ...n ]]
其中,Expression是列名,使用COMPUTE将产生额外的汇总行。
注意:在SELECT语句中使用COMPUTE BY子句时,必须与ORDER BY子句联合使用。COMPUTE BY子句中的统计字段名列表必须与ORDER BY子句中的相同或为其子集,而且二者从左到右的排列顺序必须一致。
使用时应该注意以下几点:
COMPUTE子句中指定的列必须包含在SELECT语句中,不能用别名。
使用COMPUTE BY子句时,也必须使用ORDER BY子句,且在COMPUTE BY子句中出现的列必须小于或等于ORDER BY子句中出现的列,列的顺序也要相同。
练习6:查看课程表中系部编号为01的课程信息,同时显示该系部的平均报名人数
练习7:按系部分组显示课程信息,并显示各系部的平均报名人数。
4单元总结:
一、单表查询
1、 输出表中全部列
2、 输出部分列
3、 行筛选
1) distinct消除结果集重复行,针对某一列
2) top n显示结果集的前N行
3) where子句
a. 比较运算符
b. 逻辑运算符 and or not
c. 范围运算符 between and
d. 列表运算符in
e. 模糊匹配运算符 like 通配符(%、_、[]、[^])
f. 空值运算符
4、 排序order by列名1,列名2…,列名N
5、 重命名结果集的列名称 原列名 空格 新列名
原列名 as 新列名
新列名=原列名
6、 对结果集数据进行统计计算(聚合函数sum、avg、max、min、7、 分组
1) Group by 可以结合聚合函数进行统计
2) Compute [by]可以结合聚合函数进行分组统计并显示明细
聚合函数=========compute
count)
Group by=========compute by
二、管理数据
1、insert
2、update
3、delete
--01系部有多少个班级
use xk
go
select COUNT(DepartNo) '班级数'
from Class
where DepartNo=01
--各系部有多少个班级
--实际上就是要按照系部编号进行分组,将编号相同的分为一组,计算count()
--所以有几个编号,则结果中就会有几行
select DepartNo,COUNT(*) '班级数'
from Class
group by DepartNo with cube
--计算各系部开设课程的限选人数的平均值
select DepartNo,AVG(LimitNum)
from Course
group by DepartNo with cube
--求数据库中各班级的学生数,除了班
--描述:从指定的表中进行查询,按照指定的列进行分组,值相等的的列值对
--应的行(排除不满足where的行)为一组,然后按照select子句指定的函数对各个组分别进行计算
select ClassNo ,COUNT(StuNo)
from Student
where ClassNo!=20000001
GROUP by ClassNo
--求各系部开设课程的平均学分和可以报名的总人数。
select DepartNo,AVG(Credit) '平均学分',SUM(willnum) '报名的总人数'
from Course
GROUP by DepartNo
--各个学生分别选修了几门课(一个学生可能选修多门课)
select StuNo,COUNT(*)
from stucou
group by StuNo
--各门课程分别有几个学生选修(一门课程可能会被多个学生选修)
select CouNo '课程编号',COUNT(stuno)
from stucou
group by CouNo with cube
--计算报名人数大于的各系部的课程数(03系部被where子句筛选掉)
select DepartNo,COUNT(*)
from Course
where WillNum>30
group by all DepartNo
--计算总报名人数大于的各系部的课程数(系部被having子句筛选掉)
select departno,avg(credit),sum(willnum)
from course
group by all departno
having sum(willnum)>100
--查看限选人数小于等于的各系部的总报名人数大于的课程的平均学分和报名总人数
Select departno,avg(credit),sum(willnum)
From course
where limitnum<=10
group by departno
having sum(willnum)>100