上一篇我们介绍了如何利用 CASE 表达式为 SQL 语句增加逻辑处理功能。
在上一篇行转列的示例中,我们使用了 SUM 函数;它是一个聚合函数,可以对数据进行汇总求和。SQL 提供了许多这类函数,本篇我们就来学习如何利用聚合函数实现数据报表中的汇总分析。
聚合函数
汇总分析是数据报表中的基本功能,例如销售额度的汇总统计、计算学生的平均身高以及标准差等。为此,SQL 提供了许多具有汇总功能的聚合函数。
在 SQL 中,聚合函数(Aggregate Function)用于对一组数据进行汇总计算,并且返回单个分析结果。常见的聚合函数包括:
- COUNT,统计查询结果的行数;
- AVG,计算一组数值的平均值;
- SUM,计算一组数值的总和;
- MAX ,计算一组数据中的最大值;
- MIN,计算一组数据中的最小值;
- VAR_SAMP、STDDEV_SAMP,计算一组数据的方差和标准差。
使用 COUNT 函数统计数量
COUNT(*) 函数用于统计行数。以下示例统计员工的数量:
SELECT COUNT(*) AS "员工数量" FROM employee;
员工数量 ------|
25|
查询的结果显示员工表包含 25 条记录,也就是 25 名员工。
COUNT 函数也可以统计某个字段或者表达式的数量。以下示例统计员工编号和常量 0 的个数:
SELECT COUNT(emp_id), COUNT(0) FROM employee;
COUNT(emp_id)|COUNT(0)|
-------------|--------|
25| 25|
两个统计结果都是 25,因为每个员工都有一个编号;COUNT(0) 和 COUNT(*) 的效果相同。
使用聚合函数时需要注意两点:
- 在聚合函数的参数中加上 DISTINCT 关键字,可以在计算之前排除重复值;
- 聚合函数在计算时,忽略输入值为 NULL 的数据行;COUNT(*) 除外。
我们先来看一下 COUNT 函数加上 DISTINCT 之后的效果:
SELECT COUNT(sex), COUNT(DISTINCT sex) FROM employee;
COUNT(sex)|COUNT(DISTINCT sex)|
----------|-------------------|
25| 2|
由于员工表中的性别只有“男”和“女”,加上 DISTINCT 之后统计的结果变成了 2。
如果参数中存在空值,COUNT 函数通常会忽略这些空值。以下示例基于奖金字段进行统计:
SELECT COUNT(*), COUNT(bonus), COUNT(*) - COUNT(bonus) FROM employee;
COUNT(*)|COUNT(bonus)|COUNT(*) - COUNT(bonus)|
--------|------------|-----------------------|
25| 9| 16|
从结果可以看出只有 9 名员工有奖金,其他的 16 名员工没有奖金。COUNT(*) 总是返回所有满足查询条件的行数。
最后,我们给出 COUNT 函数的完整语法:
COUNT(*) COUNT( [ALL | DISTINCT] expression)
使用 AVG 函数计算平均值
AVG 函数用于计算一组数据的平均值。以下示例用于计算所有员工的平均月薪:
SELECT AVG(salary) FROM employee;
AVG(salary)|
-----------|
9912.000000|
所有员工的平均月薪为 9912。
当 AVG 函数中包含 DISTINCT 参数时,在计算平均值之前会排除掉重复值。例如,(1、1、2)的平均值为 (1 + 2) / 2 = 1.5,而不是 (1 + 1 + 2) / 3 = 1.33。以下语句返回所有不重复的月薪的平均值:
SELECT AVG(DISTINCT salary) FROM employee;
AVG(DISTINCT salary)|
--------------------|
9865.000000|
去掉重复值之后的平均月薪为 9865,有所增加。
当 AVG 函数中存在空值时,计算之前会忽略这些空值。例如,(1,2,NULL)的平均值为 (1 + 2) / 2 = 1.5,而不是 (1 + 2) / 3 = 1。以下示例返回所有拥有奖金的员工的平均奖金:
SELECT AVG(bonus) FROM employee;
AVG(bonus) |
-----------|
6388.888889|
去除掉没有奖金的员工之后,平均奖金约为 6389。
最后,我们给出 AVG 函数的完整语法:
AVG( [ALL | DISTINCT] expression)
使用 SUM 函数进行求和
SUM 函数用于计算一组数据的总和。以下语句返回所有员工的月薪总和:
SELECT SUM(salary) FROM employee;
SUM(salary)|
-----------|
247800.00|
该公司所有员工的月薪总计为 247800。
SUM 函数也可以使用 DISTINCT 参数,在计算总和之前排除重复的值,但是很少使用。另外,SUM 函数在求和时自动忽略 NULL 值。
SUM 函数的完整语法如下:
SUM( [ALL | DISTINCT] expression)
使用 MAX 函数计算最大值
MAX 函数用于计算一组数据中的最大值。以下示例返回最后一个入职员工的入职时间:
SELECT MAX(hire_date) FROM employee;
MAX(hire_date)|
--------------|
2019-05-11|
最后一个员工的入职时间是 2019 年 5 月 11 日。
MAX 函数也可以使用 DISTINCT 参数,但是没有意义,因为结果不变。另外,MAX 函数不会考虑 NULL 值。
MAX 函数的完整语法如下:
MAX( [ALL | DISTINCT] expression)
使用 MIN 函数计算最小值
MIN 函数用于计算一组数据中的最小值。以下示例返回第一个员工的入职时间:
SELECT MIN(hire_date) FROM employee;
MIN(hire_date)|
--------------|
2000-01-01|
第一个员工的入职时间是 2000 年 1 月 1 日。
MIN 函数也可以使用 DISTINCT 参数,但是没有意义,因为结果不变。另外,MIN 函数不会考虑 NULL 值。
MIN 函数的完整语法如下:
MIN( [ALL | DISTINCT] expression)
计算方差和标准差
统计学中通常使用方差(Variance)和标准差(Standard Deviation)衡量数据的离散程度,结果越小表示数据越集中。例如在打靶比赛中,两人的平均分都是 9 环,此时方差/标准差越小说明发挥越稳定。
SQL 定义了计算样本方差/标准差和总体方差/样本差的函数,它们在各种数据库中的实现如下:
函数 | 描述 | Oracle | MySQL | SQL Server | PostgreSQL |
---|---|---|---|---|---|
STDDEV_POP | 总体标准差 | 支持 | 支持 | STDEVP | 支持 |
STDDEV_SAMP | 样本标准差 | 支持 | 支持 | STDEV | 支持 |
VAR_POP | 总体方差 | 支持 | 支持 | VARP | 支持 |
VAR_SAMP | 样本方差 | 支持 | 支持 | VAR | 支持 |
在 Oracle 和 PostgreSQL 中,STDDEV 函数也可用于计算样本标准差,VARIANCE 函数也可用于计算样本方差。 在 MySQL 中,STDDEV、STD 函数也可用于计算总体标准差,VARIANCE 函数也用于计算样本方差。
Oracle、MySQL 以及 PostgreSQL 都与标准一致,SQL Server 使用专有的函数名。以下语句分别计算员工月薪的总体标准差、样本标准差、总体方差以及样本方差:
-- Oracle、MySQL 以及 PostgreSQL 实现
SELECT STDDEV_POP(salary),STDDEV_SAMP(salary),VAR_POP(salary),VAR_SAMP(salary) FROM employee;
-- SQL Server 实现
SELECT STDEVP(salary),STDEV(salary),VARP(salary),VAR(salary) FROM employee;
该查询的结果如下,不同数据库中的精度可能存在一些细微差异:
STDDEV_POP(salary)|STDDEV_SAMP(salary)|VAR_POP(salary)|VAR_SAMP(salary)|
------------------|-------------------|---------------|----------------|
7546.004| 7701.608| 56942176| 59314766.667|
Oracle 和 MySQL 中的这些统计函数不支持 DISTINCT 参数;SQL Server 和 PostgreSQL 中的这些统计函数支持 DISTINCT 参数,在计算之前排除重复的值,但是这么做通常没有什么意义。另外,这些函数在计算时自动忽略 NULL 值。
小结
聚合函数可以用于数据的汇总分析,本篇介绍了如何使用 SQL 聚合函数统计行数、平均值、总和、最大值、最小值以及统计学中的方差和标准差。
练习题:编写 SQL 语句统计每个部门中的人数,一个部门显示为一列,返回下面的结果: