当前位置: 首页 > news >正文

SQL:聚合函数(Aggregate Functions)

目录

第一性原理出发思考 ——我们为什么需要聚合函数?

什么是聚合函数? 

常见聚合函数 + 实例讲解 

 🔸 1. COUNT() —— 计数

 🔸 2. MAX() / MIN() —— 最大 / 最小值

🔸 3. SUM() —— 求和 

🔸 4. AVG() —— 平均值 

 GROUP BY

GROUP BY 是什么? 

执行逻辑 

 GROUP BY 的重要规则

HAVING

为什么还要 HAVING? 

HAVING 是什么? 

实例讲解 

HAVING 和 WHERE 的区别 

思维图:GROUP BY + HAVING 工作流程 

第一性原理出发思考 ——我们为什么需要聚合函数?

在数据库中,查询的本质是从一堆数据中“找出我们需要的信息”。有时候我们不仅想看到“每一行”,而是想对一整列进行“汇总”,比如:

  • 一共预订了多少场电影?

  • 哪个用户最爱看电影?

  • 每部电影平均有多少人观看?

这个时候,我们就需要——聚合函数

什么是聚合函数? 

聚合函数是 MySQL 中用于对一整列的数据进行统计、计算或汇总的函数。它不是作用于“某一行”,而是作用于“一列”或“一组”数据。 


常见聚合函数 + 实例讲解 

我们来建一个简单的工资表 employees,字段如下: 

CREATE TABLE employees (id INT PRIMARY KEY AUTO_INCREMENT,name VARCHAR(50),salary INT
);

插入一些数据: 

INSERT INTO employees (name, salary) VALUES 
('Alice', 5000),
('Bob', 6000),
('Charlie', 5500),
('Diana', 7000),
('Eve', 6500),
('Frank', 5200);

 🔸 1. COUNT() —— 计数

SELECT COUNT(*) FROM employees;

 我们给数据库一个表,它扫描所有行,每遇到一行就 +1,最后告诉你一共有几行数据。

最后返回 6

SELECT COUNT(salary) FROM employees;

 与 COUNT(*) 类似,但如果有 NULL 工资的员工,不计入。

 🔸 2. MAX() / MIN() —— 最大 / 最小值

SELECT MAX(salary), MIN(salary) FROM employees;

 数据库扫描每一个值,记录当前最大/最小值,直到最后一行。

最后返回:MAX: 7000, MIN: 5000 

🔸 3. SUM() —— 求和 

SELECT SUM(salary) FROM employees;

 我们把这一列的值都加起来,输出总和。适合处理“总销售额”、“总时长”等问题。

最后返回:5000 + 6000 + 5500 + 7000 + 6500 + 5200 = 35,200
 

🔸 4. AVG() —— 平均值 

SELECT AVG(salary) FROM employees;

 就是 SUM(salary) / COUNT(salary),把总量除以人数,得到“人均”指标。

最后返回:35200 / 6 = 5866.67 

你还可以这样玩: 

-- 所有工资加 500 后的平均值是多少?
SELECT AVG(salary + 500) FROM employees;-- 平均名字长度(字符串函数 + 聚合函数)
SELECT AVG(CHAR_LENGTH(name)) FROM employees;

 GROUP BY

我们之前讲的聚合函数是对“一整列”做统计,但很多时候,我们想知道: 

各个部门的平均工资分别是多少? 

这就需要把“整张表”按部门拆成若干小组,每一组内部再用聚合函数统计。 

💡 这时候,我们就需要 GROUP BY。 

GROUP BY 是什么? 

GROUP BY 是 SQL 中的“分组器”

它把一张大表,按某个字段(或字段组合)划分成一组组数据,然后对每组单独使用聚合函数。 

执行逻辑 

SELECT A, 聚合函数(B)
FROM 表
GROUP BY A;

你在做的是:

  • 把表 按 A 的值分组

  • 每一组内部,对 B 进行聚合运算

  • 然后输出每一组的 A + 对应的聚合结果

🎯 目标:统计各个部门的平均工资 

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

这条 SQL 的背后逻辑是这样的:

  1. 扫描整张表

  2. department 字段的值,把表划分为若干组:

    • HR: [Alice, Charlie, Frank]

    • IT: [Bob, Diana]

    • Finance: [Eve]

  3. 对每组单独执行 AVG(salary)

  4. 输出每组的 department 和对应的 avg_salary

执行结果:

departmentavg_salary
HR5233.33
IT6500.00
Finance6500.00

 GROUP BY 的重要规则

规则说明
SELECT 中非聚合字段必须出现在 GROUP BY 中除非是聚合函数计算的,否则 SELECT 中的字段必须被 GROUP BY
GROUP BY 后面可以接多个字段表示按多个维度进行分组

所以 只要出现在 SELECT 中的字段,不是用聚合函数包裹的,就必须是分组的依据,也就是 GROUP BY 中出现的字段。 

整张表 → 按字段值分组 → 每组做聚合 → 输出每组统计结果

HAVING

为什么还要 HAVING? 

我们已经知道:每个部门的平均工资。但问题来了: 

❓“只想要平均工资大于 6000 的部门”怎么办? 

你可能第一反应是: 

SELECT department, AVG(salary)
FROM employees
WHERE AVG(salary) > 6000     -- 🚫 错误用法
GROUP BY department;

 ❌ 错误!
因为 WHERE 是在分组之前起作用的,根本没法识别 AVG(salary) 这种“分组后的值”。

HAVING 是什么? 

HAVING 是用来 过滤分组后的结果 的

它和 WHERE 类似,但发生在 GROUP BY 之后 

实例讲解 

🎯 问题:找出平均工资高于 6000 的部门 

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

🔍 数据回顾(之前的平均工资):

departmentavg_salary
HR5233.33
IT6500.00
Finance6500.00

📌 这条 SQL 会返回:

departmentavg_salary
IT6500.00
Finance6500.00

因为只有这两个部门的平均工资大于 6000。

🔹 统计每个部门人数大于 2 的部门:

SELECT department, COUNT(*) AS num_employees 
FROM employees 
GROUP BY department 
HAVING COUNT(*) > 2;

🔹 平均工资等于最大工资的部门

SELECT department, AVG(salary), MAX(salary) FROM employees 
GROUP BY department 
HAVING AVG(salary) = MAX(salary);

 使用别名:

SELECT department, AVG(salary) AS avg_salary
FROM employees
GROUP BY department
HAVING avg_salary > 6000;   -- ✅ 正确用法

HAVING 和 WHERE 的区别 

语句部分用途作用顺序(谁先执行)
WHERE筛选原始数据在分组之前执行
HAVING筛选分组结果在分组之后执行

 WHERE 是筛选行,HAVING 是筛选组。

WHERE 是先手,HAVING 是后手。

思维图:GROUP BY + HAVING 工作流程 

原始表↓   (WHERE)
过滤掉不满足条件的行↓   (GROUP BY)
按照字段分组↓   (聚合函数)
计算每组的结果↓   (HAVING)
筛选掉不满足条件的组↓   (SELECT)
最终展示结果

相关文章:

  • Java 接入deepseek(非流式)
  • 基于autoware.1.14与gazebo联合仿真进行激光点云循迹仿真
  • 基于领域知识的A型主动脉夹层综合分割及面向临床的评估|文献速递-深度学习医疗AI最新文献
  • 【学习笔记】文件上传漏洞--黑白盒审计
  • 文章记单词 | 第37篇(六级)
  • 云服务器和物理服务器
  • AI写程序: 多线程网络扫描网段ip工具
  • 内网穿透服务器—FRP
  • 颚式破碎机的设计
  • c# 简单实现将Message的内容保存到txt中,超过100个则清理旧文件
  • Linux:线程的同步与互斥(生产者消费者模型的demo)
  • Function Calling的时序图(含示例)
  • FA-YOLO:基于FMDS与AGMF的高效目标检测算法解析
  • C++指针与内存管理深度解析
  • TDengine Restful 接口API
  • 【机试】高精度
  • Valgrind内存调试工具详解
  • PGSql常用操作命令
  • DeepSeek-R3、GPT-4o 与 Claude-3.5-Sonnet 全面对比:性能、应用场景与技术解析
  • docker一次给所有容器限制内存大小
  • 马上评|机器人马拉松,也是具身智能产业的加速跑
  • 瑞安房地产王颖:房地产市场看到很好的信号,上海项目销售压力不大
  • 巡视杭州市工作动员会召开,市长姚高员表态
  • 释新闻|特朗普喊话鲍威尔早点走人,美国总统能否解雇美联储主席?
  • 钧正平发声:擅自更改地图标注,谷歌想当南海搅局者?!
  • 秦洪看盘|量能虽萎缩,但交易情绪尚可