聚合函数
聚合函数
🌍 生活类比
想象你是一家超市的经理,面对一堆销售小票:
- COUNT = 数一数今天有多少张小票(计数)
- SUM = 把所有小票的金额加起来(求和)
- AVG = 算一下平均每张小票多少钱(平均)
- MAX = 找出金额最大的那张小票(最大值)
- MIN = 找出金额最小的那张小票(最小值)
聚合函数就是SQL里的"计算器",帮你在大量数据中快速算出汇总结果。
🎯 核心概念
COUNT — 计数
COUNT 用于统计行数。有两种常见写法:
-- COUNT(*):统计所有行(包含NULL行)
SELECT COUNT(*) AS total_employees FROM employees;
-- COUNT(列名):统计该列非NULL的行数
SELECT COUNT(email) AS has_email FROM employees;
| 写法 | 说明 |
|---|---|
COUNT(*) |
统计所有行,不管是否有NULL |
COUNT(列名) |
只统计该列非NULL的行 |
COUNT(DISTINCT 列名) |
统计该列去重后的非NULL行数 |
SUM — 求和
对数值列求总和,自动忽略NULL值。
SELECT SUM(salary) AS total_salary FROM employees;
AVG — 平均值
对数值列求平均,自动忽略NULL值(NULL不参与计算)。
SELECT AVG(salary) AS avg_salary FROM employees;
MAX / MIN — 最大值 / 最小值
找出列中的最大或最小值,自动忽略NULL值。
SELECT MAX(salary) AS highest, MIN(salary) AS lowest FROM employees;
聚合函数与 NULL 的行为
这是初学者最容易踩的坑:
| 函数 | 如何处理NULL |
|---|---|
COUNT(*) |
NULL也计入(统计行数) |
COUNT(列名) |
忽略NULL |
SUM(列名) |
忽略NULL |
AVG(列名) |
忽略NULL(分母也不含NULL行) |
MAX(列名) |
忽略NULL |
MIN(列名) |
忽略NULL |
-- 假设employees表有10行,其中email列有3个NULL
SELECT COUNT(*) AS total, -- 10
COUNT(email) AS has_email -- 7
FROM employees;
AVG 计算时,分母是非NULL的行数,不是总行数。如果5个员工中2人工资为NULL,AVG(salary) 只用3人的工资计算平均值。
DISTINCT 去重聚合
在聚合函数中使用 DISTINCT 可以先去重再聚合:
-- 有多少个不同的部门有员工?
SELECT COUNT(DISTINCT department_id) AS dept_count FROM employees;
-- 所有不同工资的总和(去重后求和)
SELECT SUM(DISTINCT salary) AS unique_salary_sum FROM employees;
📝 基本语法
-- 聚合函数基本语法
SELECT 聚合函数(列名) AS 别名
FROM 表名
WHERE 条件;
-- 多个聚合函数可以同时使用
SELECT COUNT(*) AS 总数,
SUM(列名) AS 总和,
AVG(列名) AS 平均,
MAX(列名) AS 最大,
MIN(列名) AS 最小
FROM 表名;
-- DISTINCT 去重聚合
SELECT COUNT(DISTINCT 列名) AS 去重计数
FROM 表名;
- 聚合函数通常与
GROUP BY配合使用(下一课学习),也可以单独使用(对全表聚合) - 聚合函数不能直接用在
WHERE条件中,需要用HAVING(后续学习) NULL在聚合运算中被自动跳过,这既是特性也是陷阱,务必注意
📌 示例
示例:统计员工基本信息
SELECT COUNT(*) AS 员工总数,
COUNT(email) AS 有邮箱的人数,
SUM(salary) AS 工资总额,
AVG(salary) AS 平均工资,
MAX(salary) AS 最高工资,
MIN(salary) AS 最低工资
FROM employees;
输出:
员工总数 有邮箱的人数 工资总额 平均工资 最高工资 最低工资
-------- ----------- ---------- --------- --------- ---------
8 7 112000.00 14000.00 20000.00 9000.00
示例:按条件聚合 + DISTINCT
-- 技术部有多少员工?有多少种不同的工资?
SELECT COUNT(*) AS 技术部人数,
COUNT(DISTINCT salary) AS 不同工资数,
AVG(salary) AS 技术部平均工资
FROM employees
WHERE department_id = 1;
输出:
技术部人数 不同工资数 技术部平均工资
--------- ---------- -------------
3 3 17666.67
WHERE 先筛选出技术部的员工,再对筛选结果聚合。
示例:多个聚合函数 + 条件过滤
-- 订单金额统计:只统计已完成的订单
SELECT COUNT(*) AS 订单数量,
SUM(total_amount) AS 总金额,
AVG(total_amount) AS 平均订单金额,
MAX(total_amount) AS 最大订单,
MIN(total_amount) AS 最小订单
FROM orders
WHERE status = 'completed';
输出:
订单数量 总金额 平均订单金额 最大订单 最小订单
------- ---------- ----------- --------- ---------
5 42500.00 8500.00 15000.00 2800.00
WHERE 先过滤出已完成的订单,再对这些订单进行聚合计算。注意 WHERE 在聚合之前执行。
🎬 场景演练
场景一:HR报表——部门薪资概况
HR需要一份报表,了解公司整体薪资情况以及有多少员工有联系方式。
SELECT
COUNT(*) AS 总人数,
COUNT(email) + COUNT(phone) AS 联系方式总数,
SUM(salary) AS 年度工资支出,
AVG(salary) AS 平均月薪,
MAX(salary) - MIN(salary) AS 最大薪资差距
FROM employees
WHERE hire_date >= '2024-01-01';
WHERE 筛选2024年以后入职的员工,再用多个聚合函数从不同维度汇总数据。
场景二:销售分析——订单价值分布
分析所有已发货订单的价值分布。
SELECT
COUNT(*) AS 已发货订单数,
COUNT(DISTINCT customer_id) AS 不同客户数,
SUM(total_amount) AS 总销售额,
AVG(total_amount) AS 客单价,
MAX(total_amount) AS 最大订单,
MIN(total_amount) AS 最小订单
FROM orders
WHERE status = 'shipped';
COUNT(DISTINCT customer_id) 帮助我们了解有多少不同的客户下过单,而不是订单数。
❓ 常见问题
Q:COUNT(*) 和 COUNT(1) 有区别吗? A: 在现代数据库中几乎没有区别,优化器会将它们处理为相同的执行计划。
COUNT(*)是更规范的写法,推荐使用。
Q:AVG遇到NULL怎么算? A:
AVG会忽略NULL值。假设5人中有2人工资为NULL,AVG(salary)只用3人的工资计算,而不是除以5。如果想把NULL当作0计算,需要用AVG(COALESCE(salary, 0))。
Q:聚合函数能嵌套使用吗? A: 不能直接嵌套。比如
MAX(AVG(salary))会报错。要实现"找出平均工资最高的部门",需要用GROUP BY+ORDER BY AVG(salary) DESC LIMIT 1,或者用子查询。
Q:SUM遇到空表会返回什么? A:
SUM、AVG、MAX、MIN在空表或全为NULL时返回NULL,而不是0。COUNT返回0。如果需要返回0,用COALESCE(SUM(列名), 0)。
📖 小节
| 函数 | 作用 | NULL处理 | 搭配DISTINCT |
|---|---|---|---|
| COUNT(*) | 统计所有行 | 计入 | 不适用 |
| COUNT(列) | 统计非NULL行 | 忽略 | ✅ |
| SUM(列) | 求和 | 忽略 | ✅ |
| AVG(列) | 平均值 | 忽略(分母也不含) | ✅ |
| MAX(列) | 最大值 | 忽略 | ✅ |
| MIN(列) | 最小值 | 忽略 | ✅ |
- 聚合函数是SQL的"统计工具",将多行数据压缩为一个汇总值
- 聚合函数自动忽略NULL,但
COUNT(*)例外 DISTINCT可以在聚合前去重- 聚合函数不能用在
WHERE中,需要用HAVING(下一课学习)
📝 作业
作业1(⭐):查询 employees 表,统计总人数、最高工资、最低工资和平均工资。
作业2(⭐⭐):查询 orders 表,统计2025年的已完成订单数量、总金额和平均金额。要求:只计算 status = 'completed' 的订单。
作业3(⭐⭐⭐):查询 employees 表,统计每个薪资等级的人数。规则:工资 >= 15000 为"高薪",>= 10000 为"中等",其余为"初级"。提示:使用 CASE WHEN 配合聚合函数。
下一课
👉 14-group-by - 分组查询:学习 GROUP BY 分组查询,掌握按类别统计、HAVING 过滤分组等技能!



