SQL中常用的聚合函数完整清单(详解COUNT/SUM/AVG/MIN/MAX的作用与NULL处理)

SQL 的聚合函数对一组值做计算并返回单个汇总值,是数据分析的基础工具。最常用的是五个核心函数:COUNT(计数)、SUM(求和)、AVG(平均值)、MIN(最小值)、MAX(最大值)。它们通常与 GROUP BY 配合,把数据按维度分组后再汇总;除 COUNT(*) 外,其余函数默认忽略 NULL 值。据 MySQL 官方文档(Aggregate Function Descriptions)记载,聚合函数作用于”值的集合”,常借助 GROUP BY 把值分成子集;Microsoft Learn 的 T-SQL 教程也明确,聚合函数返回标量值,可在 SELECT、HAVING、ORDER BY 中使用,但不能直接出现在 WHERE 子句里。

一、聚合函数的工作前提

普通查询一次处理一行,返回的行与原表一一对应;聚合函数则”压缩”多行——把一组值收敛成单个结果。据 LeetCode SQL50 的整理,这种”多行进、单行出”的特性决定了三个基本约束:

  • 忽略 NULL:除 COUNT(*) 外,所有聚合函数跳过 NULL 值,不参与计数或计算。
  • 不能用于 WHERE:行级过滤发生在聚合之前,WHERE 里不能写 AVG(salary) > 5000,这种”对结果再过滤”要交给 HAVING。
  • 非聚合列必须进 GROUP BY:SELECT 中既写了聚合函数又写了普通列时,普通列必须出现在 GROUP BY 中,否则多数引擎报 only_full_group_by 类错误。

二、五大核心函数逐一拆解

函数 作用 对 NULL 的处理 适用类型
COUNT(*) 统计所有行数 含 NULL 行也计入 任意
COUNT(col) 统计非 NULL 的列值数 忽略 NULL 任意
SUM(col) 数值列求和 忽略 NULL 数值
AVG(col) 数值列平均值(SUM/COUNT) 忽略 NULL 数值
MIN(col) 最小值 忽略 NULL 数值/日期/字符串
MAX(col) 最大值 忽略 NULL 数值/日期/字符串

COUNT:三种写法含义不同

sql

SELECT COUNT(*)          AS total_rows,   -- 统计所有行,含 NULL
       COUNT(bonus)      AS with_bonus,   -- 只统计 bonus 非 NULL 的行
       COUNT(DISTINCT dept) AS dept_cnt   -- 统计不重复的部门数
FROM employees;

COUNT(*) 与 COUNT(1) 在主流引擎(MySQL、SQL Server、PostgreSQL)中结果等价,都是全行计数;COUNT(col) 与 COUNT(DISTINCT col) 才涉及空值与非空去重。leapcell 的指南强调,COUNT(*) 是唯一把 NULL 行也算进去的形式。

SUM 与 AVG:只认数值

sql

SELECT SUM(salary) AS payroll,
       AVG(salary) AS avg_salary
FROM employees;

二者都忽略 NULL。要理解 AVG 的本质是 SUM/COUNT(非NULL),因此 AVG(bonus) 的分母是”非 NULL 的 bonus 行数”,而非总行数——这是很多人算错平均值的原因。GeeksforGeeks 与 sqlmastery 均指出,若全部为 NULL,SUM/AVG 返回 NULL 而非 0。

MIN 与 MAX:不限数值

MIN/MAX 不仅支持数字,也支持日期(最早/最晚)和字符串(按排序规则的首/尾)。Microsoft Learn 举例:用 MIN(CompanyName)、MAX(CompanyName) 即可取字母序的首尾公司名,无需额外排序。

sql

SELECT MIN(hire_date) AS earliest,
       MAX(hire_date) AS latest
FROM employees;

三、与 GROUP BY 搭配分组汇总

聚合函数真正的威力在分组。下面按部门求平均薪资:

sql

SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department;

GROUP BY 先把行按 department 分桶,再在每个桶内跑聚合。MySQL 官方文档说明,没有 GROUP BY 时,整张表被当作一个组;GROUP BY 把”值的集合”切成多个子集分别汇总。

四、HAVING:对聚合结果再过滤

WHERE 过滤行、HAVING 过滤组,二者顺序不同。要筛出”平均薪资超 600 的部门”:

sql

SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department
HAVING AVG(salary) > 600;

Leapcell 用同一例子说明:WHERE 无法引用聚合结果,必须改用 HAVING——它作用于分组之后的汇总值。

五、进阶:条件聚合与扩展函数

条件聚合(CASE + 聚合)

把行级判断嵌进聚合,一行得出多维度计数:

sql

SELECT COUNT(*) AS total,
       SUM(CASE WHEN status = 'approved' THEN 1 ELSE 0 END) AS approved,
       SUM(CASE WHEN status = 'rejected' THEN 1 ELSE 0 END) AS rejected
FROM orders;

LeetCode SQL50 把此列为高频技巧:无需多次 GROUP BY,单条语句得到各状态数量。

字符串拼接与统计类

MySQL 提供 GROUP_CONCAT()(PostgreSQL/SQL Server 对应 STRING_AGG())把分组内的文本拼成一行;STDDEV()/VARIANCE() 给出标准差与方差,用于衡量数据离散程度。MySQL 9.0 文档的函数表中还列有 BIT_AND/BIT_OR、JSON_ARRAYAGG/JSON_OBJECTAGG 等专用聚合,覆盖位运算与 JSON 汇总场景。

窗口化能力

多数聚合函数在 MySQL 8.0+、SQL Server、PostgreSQL 中可加 OVER() 转为窗口函数,在不折叠行的前提下完成分组计算,这是它在”聚合”与”窗口函数”两类用法间的桥梁。

六、使用聚合函数的执行步骤

  1. 明确要算的指标(计数、求和、均值、极值),选对函数。
  2. 确定分组维度,写 GROUP BY;非聚合列必须进 GROUP BY。
  3. 处理空值:确认 COUNT(*) 与 COUNT(col) 的语义差异,避免均值分母算错。
  4. 用 WHERE 先过滤行,再 GROUP BY 分组;对结果过滤用 HAVING。
  5. 需要单 SQL 多维度统计时,用 CASE WHEN 做条件聚合。

常见问题(FAQ)

COUNT(*) 和 COUNT(1) 有区别吗?
主流引擎结果相同,都是统计所有行(含 NULL);差异仅在上古版本的微观实现,现代优化器已等价。

AVG 算出来不对,为什么?
它只除以非 NULL 值的个数,忽略 NULL 行。含空值时分母比你预期的小,需先确认数据。

聚合结果能用 WHERE 过滤吗?
不能,WHERE 在聚合前执行。对汇总值过滤必须用 HAVING。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 qiqicto@qq.com 举报,一经查实,本站将立刻删除。
赞 (0)
云端房东的头像云端房东普通用户

相关推荐

返回顶部