SQL 聚合函数详解:COUNT、SUM、AVG、MIN、MAX

你是否曾想过,数据库如何能够瞬间告诉你全年的总销售额、客户的平均年龄,或者上个月下了多少订单?答案就在 SQL 聚合函数中------这些强大的工具可以将多行数据转换为有意义的汇总信息。

聚合函数将多行数据汇总为单个指标

在本指南中,我们将探讨五个核心聚合函数:COUNTSUMAVGMINMAX。读完本文后,你将准确了解何时以及如何使用每个函数,包括一些连经验丰富的开发人员都会犯的常见错误。

什么是聚合函数?

聚合函数(Aggregate Functions)对多行数据执行计算,并返回单个结果。与处理单个值的常规函数不同,聚合函数会将数据"折叠"成汇总统计信息。

以下是快速概览:

函数 用途 返回值类型
COUNT() 计数行或非 NULL 值 整数
SUM() 求和数值 数字
AVG() 计算平均值 数字
MIN() 查找最小值 与输入相同
MAX() 查找最大值 与输入相同

核心特点

  • 多行输入,单个输出:处理多行数据,返回一个汇总值
  • 自动忽略 NULL:大多数聚合函数会自动忽略 NULL 值
  • 与 GROUP BY 结合:可以按组进行汇总
  • 适用范围广:MIN 和 MAX 可用于数字、字符串、日期等多种数据类型

COUNT:计数行和值

COUNT 可能是最常用的聚合函数。但你知道吗,它有三种不同的使用方式?

COUNT(*) vs COUNT(column) vs COUNT(DISTINCT column)

sql 复制代码
-- 计数所有行(包括 NULL)
SELECT COUNT(*) FROM orders;

-- 计数列中的非 NULL 值
SELECT COUNT(shipping_date) FROM orders;

-- 计数唯一的非 NULL 值
SELECT COUNT(DISTINCT customer_id) FROM orders;

关键区别

  • COUNT(*):计数所有行,包括包含 NULL 的行
  • COUNT(column):只计数该列中非 NULL 的行
  • COUNT(DISTINCT column):计数该列中唯一的非 NULL 值

交互式示例:COUNT 的三种用法

示例数据(employees 表)

id name department salary bonus
1 Alice Engineering 90000 5000
2 Bob Engineering 85000 NULL
3 Carol Sales 70000 3000
4 Dave Sales 65000 NULL
5 Eve Marketing 75000 4000

查询

sql 复制代码
-- 尝试不同的 COUNT 变体
SELECT 
  COUNT(*) AS total_rows,
  COUNT(bonus) AS with_bonus,
  COUNT(DISTINCT department) AS unique_departments
FROM employees;

查询结果

total_rows with_bonus unique_departments
5 3 3

结果解读

  • total_rows = 5:表中共有 5 行数据
  • with_bonus = 3:只有 3 个员工有奖金(Alice、Carol、Eve)
  • unique_departments = 3:有 3 个不同的部门(Engineering、Sales、Marketing)

注意COUNT(bonus) 返回 3(只计数非 NULL 值),而 COUNT(*) 返回 5(所有行)。

SUM:求和数值

SUM 将数值列中的所有值相加。它会自动忽略 NULL 值。

sql 复制代码
SELECT SUM(amount) AS total_sales
FROM orders
WHERE order_date >= '2025-01-01';

常见陷阱:NULL 值处理

对所有值都是 NULL 的列求和会返回 NULL,而不是 0。使用 COALESCE 来处理这种情况:

sql 复制代码
SELECT COALESCE(SUM(amount), 0) AS total_sales
FROM orders
WHERE order_date >= '2099-01-01'; -- 没有匹配的行

交互式示例:SUM 和 NULL 处理

示例数据(orders 表)

order_id amount discount bonus
1 1000 50 100
2 1500 NULL NULL
3 2000 100 200
4 1200 NULL NULL
5 1800 75 150

查询

sql 复制代码
-- 计算总额并查看 NULL 处理
SELECT 
  SUM(amount) AS total_sales,
  SUM(discount) AS total_discount,
  COALESCE(SUM(bonus), 0) AS total_bonus
FROM orders;

查询结果

total_sales total_discount total_bonus
7500 225 450

结果解读

  • total_sales = 7500:所有订单金额之和(1000 + 1500 + 2000 + 1200 + 1800)
  • total_discount = 225:所有折扣之和(50 + 100 + 75),NULL 值被忽略
  • total_bonus = 450:所有奖金之和(100 + 200 + 150),NULL 值被忽略

关键点

  • SUM 自动忽略 NULL 值
  • 如果所有值都是 NULL,SUM 返回 NULL
  • 使用 COALESCE 将 NULL 转换为 0

AVG:计算平均值

AVG 计算数值列的算术平均值。与 SUM 一样,它会忽略 NULL 值------这有时会导致意外的结果。

sql 复制代码
SELECT AVG(salary) AS avg_salary
FROM employees;

重要提示:AVG 只考虑非 NULL 值

AVG 在计算时只考虑非 NULL 值。如果你有 10 个员工,但只有 8 个有薪资数据,平均值是基于这 8 个计算的。

交互式示例:AVG 与手动计算对比

示例数据(reviews 表)

review_id product_id rating
1 101 5
2 101 4
3 101 NULL
4 101 3
5 101 5

查询

sql 复制代码
-- 比较 AVG 与手动计算
SELECT 
  AVG(rating) AS avg_rating,
  SUM(rating) AS sum_rating,
  COUNT(rating) AS count_rating,
  SUM(rating) * 1.0 / COUNT(rating) AS manual_avg
FROM reviews;

查询结果

avg_rating sum_rating count_rating manual_avg
4.25 17 4 4.25

结果解读

  • avg_rating = 4.25:AVG 函数自动计算平均值
  • sum_rating = 17:所有评分之和(5 + 4 + 3 + 5),NULL 被忽略
  • count_rating = 4:非 NULL 评分的数量
  • manual_avg = 4.25:手动计算的平均值(17 / 4)

关键点

  • AVG 只考虑非 NULL 值
  • 如果有 5 条记录但只有 4 个非 NULL 值,平均值基于这 4 个值
  • 手动计算:SUM(column) / COUNT(column)

MIN 和 MAX:查找极值

MINMAX 适用于任何可比较的数据类型------数字、字符串、日期等。

sql 复制代码
SELECT 
  MIN(order_date) AS first_order,
  MAX(order_date) AS last_order,
  MIN(amount) AS smallest_order,
  MAX(amount) AS largest_order
FROM orders;

专业提示:字符串的 MIN 和 MAX

对于字符串,MIN 返回"字母顺序最前"的值,MAX 返回"字母顺序最后"的值。

交互式示例:不同数据类型的极值

示例数据(employees 表)

id name hire_date salary
1 Alice 2020-01-15 90000
2 Bob 2019-06-20 85000
3 Carol 2021-03-10 70000
4 Dave 2018-11-05 65000
5 Eve 2022-07-22 75000

查询

sql 复制代码
-- 查找不同数据类型的极值
SELECT 
  MIN(hire_date) AS earliest_hire,
  MAX(hire_date) AS latest_hire,
  MIN(salary) AS min_salary,
  MAX(salary) AS max_salary,
  MIN(name) AS first_name_alpha,
  MAX(name) AS last_name_alpha
FROM employees;

查询结果

earliest_hire latest_hire min_salary max_salary first_name_alpha last_name_alpha
2018-11-05 2022-07-22 65000 90000 Alice Eve

结果解读

  • earliest_hire = 2018-11-05:最早的雇佣日期(Dave)
  • latest_hire = 2022-07-22:最晚的雇佣日期(Eve)
  • min_salary = 65000:最低薪资(Dave)
  • max_salary = 90000:最高薪资(Alice)
  • first_name_alpha = Alice:字母顺序最前的名字
  • last_name_alpha = Eve:字母顺序最后的名字

关键点

  • MIN 和 MAX 适用于数字、字符串、日期等多种数据类型
  • 对于字符串,按字母顺序比较
  • 对于日期,按时间顺序比较

结合 GROUP BY 使用聚合函数

聚合函数与 GROUP BY 结合使用时会更加强大。你可以为每个组获得汇总信息,而不是整个表的单个汇总。

sql 复制代码
SELECT 
  department,
  COUNT(*) AS employee_count,
  AVG(salary) AS avg_salary,
  MAX(salary) AS max_salary
FROM employees
GROUP BY department;

交互式示例:按部门汇总

示例数据(employees 表)

id name department salary
1 Alice Engineering 90000
2 Bob Engineering 85000
3 Carol Sales 70000
4 Dave Sales 65000
5 Eve Marketing 75000
6 Frank Engineering 95000
7 Grace Sales 72000

查询

sql 复制代码
-- 按部门汇总
SELECT 
  department,
  COUNT(*) AS headcount,
  SUM(salary) AS total_payroll,
  ROUND(AVG(salary), 2) AS avg_salary,
  MIN(salary) AS min_salary,
  MAX(salary) AS max_salary
FROM employees
GROUP BY department;

查询结果

department headcount total_payroll avg_salary min_salary max_salary
Engineering 3 270000 90000.00 85000 95000
Sales 3 207000 69000.00 65000 72000
Marketing 1 75000 75000.00 75000 75000

结果解读

  • Engineering 部门:3 名员工,总薪资 270,000,平均薪资 90,000
  • Sales 部门:3 名员工,总薪资 207,000,平均薪资 69,000
  • Marketing 部门:1 名员工,总薪资 75,000,平均薪资 75,000

关键点

  • GROUP BY 将数据分组,每组单独计算聚合函数
  • 可以在一个查询中使用多个聚合函数
  • 使用 ROUND 函数使平均值更易读

常见错误

1. 混合聚合列和非聚合列

这是一个经典错误:

sql 复制代码
-- ❌ 错误:name 既没有聚合也没有分组
SELECT name, COUNT(*) FROM employees;

-- ✅ 正确:按 name 分组
SELECT name, COUNT(*) FROM employees GROUP BY name;

错误原因

  • 当使用聚合函数时,SELECT 中的所有非聚合列都必须出现在 GROUP BY 中
  • 否则数据库不知道如何处理这些列

2. 忘记 NULL 行为

sql 复制代码
-- 如果所有值都是 NULL,SUM 返回 NULL(不是 0)
SELECT COALESCE(SUM(bonus), 0) AS total_bonus FROM employees;

最佳实践

  • 始终使用 COALESCE 或 IFNULL 处理可能的 NULL 结果
  • 特别是在报表和仪表板中,0 比 NULL 更友好

3. 在整数列上使用 AVG

在某些数据库中,对整数列使用 AVG 会返回整数。转换类型以避免这种情况:

sql 复制代码
SELECT AVG(CAST(rating AS REAL)) FROM reviews;
-- 或者:AVG(rating * 1.0)

示例

错误方式 正确方式
AVG(rating) → 4(整数除法) AVG(rating * 1.0) → 4.25(浮点除法)

最佳实践

1. 使用 COUNT(*) 计数行

COUNT(*) 是计数所有行的最清晰方式。

sql 复制代码
-- ✅ 推荐
SELECT COUNT(*) FROM orders;

-- ❌ 不推荐(除非你确实只想计数非 NULL 值)
SELECT COUNT(order_id) FROM orders;

2. 使用 COALESCE 处理 SUM/AVG

保护查询免受 NULL 结果的影响,特别是当没有行匹配时。

sql 复制代码
SELECT 
  COALESCE(SUM(amount), 0) AS total_sales,
  COALESCE(AVG(amount), 0) AS avg_sales
FROM orders
WHERE order_date >= '2099-01-01'; -- 没有匹配的行

3. 四舍五入 AVG 结果

ROUND(AVG(salary), 2) 提供更清晰的输出。

sql 复制代码
-- ❌ 不易读
SELECT AVG(salary) FROM employees;
-- 结果:75432.8571428571

-- ✅ 易读
SELECT ROUND(AVG(salary), 2) FROM employees;
-- 结果:75432.86

4. 结合 HAVING 进行过滤聚合

在分组后过滤使用 HAVING

sql 复制代码
-- 查找平均薪资超过 80000 的部门
SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department
HAVING AVG(salary) > 80000;

WHERE vs HAVING

特性 WHERE HAVING
过滤时机 分组前 分组后
可用列 原始列 聚合结果
示例 WHERE salary > 50000 HAVING AVG(salary) > 80000

实际应用场景

1. 销售报表

sql 复制代码
-- 按月汇总销售数据
SELECT 
  DATE_TRUNC('month', order_date) AS month,
  COUNT(*) AS order_count,
  SUM(amount) AS total_revenue,
  ROUND(AVG(amount), 2) AS avg_order_value,
  MIN(amount) AS min_order,
  MAX(amount) AS max_order
FROM orders
WHERE order_date >= '2025-01-01'
GROUP BY DATE_TRUNC('month', order_date)
ORDER BY month;

2. 用户行为分析

sql 复制代码
-- 分析用户活跃度
SELECT 
  user_id,
  COUNT(*) AS login_count,
  MIN(login_date) AS first_login,
  MAX(login_date) AS last_login,
  COUNT(DISTINCT DATE(login_date)) AS active_days
FROM user_logins
WHERE login_date >= CURRENT_DATE - INTERVAL '30 days'
GROUP BY user_id
HAVING COUNT(*) >= 10;

3. 库存管理

sql 复制代码
-- 库存统计
SELECT 
  category,
  COUNT(*) AS product_count,
  SUM(quantity) AS total_stock,
  AVG(price) AS avg_price,
  MIN(quantity) AS min_stock,
  MAX(quantity) AS max_stock
FROM inventory
GROUP BY category
HAVING SUM(quantity) < 100; -- 库存不足的类别

4. 性能监控

sql 复制代码
-- API 响应时间分析
SELECT 
  endpoint,
  COUNT(*) AS request_count,
  ROUND(AVG(response_time_ms), 2) AS avg_response_time,
  MIN(response_time_ms) AS min_response_time,
  MAX(response_time_ms) AS max_response_time
FROM api_logs
WHERE log_date >= CURRENT_DATE
GROUP BY endpoint
HAVING AVG(response_time_ms) > 1000; -- 响应时间超过 1 秒的端点

结论

SQL 聚合函数是数据分析的核心工具。记住:

  • COUNT 计数行或非 NULL 值
  • SUM 求和数字(忽略 NULL)
  • AVG 计算平均值(忽略 NULL)
  • MIN/MAX 查找极值(适用于任何可比较类型)

关键要点

  • 聚合函数通常会忽略 NULL 值,但这可能导致意外结果
  • 始终使用 COALESCE 确保非 NULL 结果
  • 结合 GROUP BY 使用可以进行分组汇总
  • 使用 HAVING 过滤聚合结果

现在,去尝试这些函数吧!在实际项目中实验不同的查询,以巩固你的理解。


相关文章推荐


本文转载自 www.hisqlboy.com

原文标题:SQL Aggregate Functions: COUNT, SUM, AVG, MIN, MAX Explained

原文链接:https://www.hisqlboy.com/blog/sql-aggregate-functions-explained

原作者:SQL Boy Team

转载日期:2026-02-15

著作权归原作者所有。本文仅用于学习交流,非商业用途。

相关推荐
w***29851 小时前
MySQL 创建新用户及授予权限的完整流程
数据库·mysql
heimeiyingwang1 小时前
向量数据库在大模型 RAG 中的核心作用与实践
数据库·人工智能·微服务
weed0002 小时前
MySQL官网驱动下载(jar包驱动和ODBC驱动)【详细教程】
数据库·mysql
青衫码上行2 小时前
Redis新数据类型 - Bitmap、HyperLogLog、Geospatial
数据库·redis·缓存
dc_00122 小时前
MySQL无法连接到本地localhost的解决办法2024.11.8
数据库·mysql·adb
SQL必知必会2 小时前
使用 SQL 实现帕累托原则(80/20 法则)
大数据·数据库·sql
q***76563 小时前
MySQL 中如何进行 SQL 调优
android·sql·mysql
2401_848009723 小时前
Redis零基础入门学习
数据库·redis·学习
NEXT063 小时前
2026 技术风向:为什么在 AI 时代,PostgreSQL 彻底成为了全栈工程师的首选数据库
前端·数据库·ai编程