1. MySQL聚合函数基础概念与核心用法MySQL中的聚合函数是数据处理中不可或缺的工具它们对一组值执行计算并返回单个值。这些函数通常与GROUP BY子句配合使用能够实现复杂的数据统计和分析需求。1.1 五大基础聚合函数详解COUNT函数是最常用的聚合函数之一它有几种变体COUNT(*)统计所有行数包括NULL值COUNT(列名)统计指定列非NULL值的行数COUNT(DISTINCT 列名)统计指定列不同非NULL值的数量实际项目中我经常用COUNT(*)来快速获取表记录数但要注意在大表上执行可能影响性能。而COUNT(DISTINCT 列名)在统计UV唯一访问量等场景特别有用。SUM和AVG函数处理数值计算-- 计算销售总额 SELECT SUM(amount) FROM sales; -- 计算平均订单金额 SELECT AVG(amount) FROM orders;这里有个重要细节AVG函数会自动忽略NULL值。如果需要将NULL视为0参与计算要使用AVG(IFNULL(列名, 0))。MAX和MIN函数用于极值查找-- 查找最高和最低温度记录 SELECT MAX(temperature), MIN(temperature) FROM weather_data;我在实际工作中发现当所有值都为NULL时MAX/MIN会返回NULL这点在报表开发时要特别注意处理。1.2 NULL值的特殊处理机制聚合函数对NULL的处理方式非常一致除了COUNT(*)其他函数都会忽略NULL值。这个特性有时会导致非预期的结果-- 示例表数据 CREATE TABLE test ( id INT, value INT ); INSERT INTO test VALUES (1, 10), (2, NULL), (3, 20); -- 以下查询返回2而非3 SELECT COUNT(value) FROM test;在金融系统中我曾遇到过一个坑计算平均资产时由于NULL值被忽略导致结果偏高。解决方案是使用IFNULL函数SELECT AVG(IFNULL(value, 0)) FROM test;2. GROUP BY分组聚合的深度应用2.1 单列与多列分组实战GROUP BY允许我们根据一个或多个列对结果集进行分组。基本语法SELECT 列1, 列2, 聚合函数(列3) FROM 表名 GROUP BY 列1, 列2;单列分组示例按部门统计薪资SELECT department, AVG(salary) FROM employees GROUP BY department;多列分组示例按部门和职位统计SELECT department, job_title, COUNT(*) FROM employees GROUP BY department, job_title;我在人力资源系统开发中经常使用多列分组生成组织架构分析报表。一个经验是GROUP BY子句中的列顺序会影响分组粒度应该把最粗粒度的列放在前面。2.2 GROUP_CONCAT的巧妙用法GROUP_CONCAT函数可以将分组内的多个值连接成一个字符串这在某些场景下非常实用-- 获取每个部门的所有员工ID列表 SELECT department, GROUP_CONCAT(employee_id) FROM employees GROUP BY department;高级用法包括指定分隔符GROUP_CONCAT(列名 SEPARATOR |)结果排序GROUP_CONCAT(列名 ORDER BY 列名 DESC)去重GROUP_CONCAT(DISTINCT 列名)在开发一个权限管理系统时我使用GROUP_CONCAT快速生成了用户-角色的映射关系报表大大简化了前端展示逻辑。2.3 WITH ROLLUP实现多级汇总WITH ROLLUP可以生成分组的小计和总计行-- 按地区和产品类别统计销售并生成小计和总计 SELECT region, category, SUM(sales) FROM sales_data GROUP BY region, category WITH ROLLUP;结果会包含每个region和category组合的明细每个region的小计行category为NULL总计行region和category都为NULL在财务系统中这个功能可以自动生成多级汇总报表但要注意NULL值的识别处理。3. HAVING子句的过滤技巧3.1 HAVING与WHERE的区别WHERE和HAVING都用于过滤数据但关键区别在于WHERE在分组前过滤行HAVING在分组后过滤组-- 错误示例WHERE中不能使用聚合函数 SELECT department, AVG(salary) FROM employees WHERE AVG(salary) 5000 -- 这里会报错 GROUP BY department; -- 正确写法 SELECT department, AVG(salary) FROM employees GROUP BY department HAVING AVG(salary) 5000;在电商数据分析中我经常用HAVING找出平均订单金额超过1000元的高价值客户群体。3.2 复杂HAVING条件构建HAVING支持复杂的条件表达式-- 找出销售额超过1万且订单数大于5的销售员 SELECT salesperson, SUM(amount), COUNT(*) FROM orders GROUP BY salesperson HAVING SUM(amount) 10000 AND COUNT(*) 5;一个性能优化技巧尽可能在WHERE阶段过滤掉不需要的行减少GROUP BY处理的数据量。例如-- 更高效的写法先过滤2023年的数据再分组 SELECT product_id, SUM(quantity) FROM orders WHERE order_date BETWEEN 2023-01-01 AND 2023-12-31 GROUP BY product_id HAVING SUM(quantity) 100;4. 高级聚合技巧与性能优化4.1 多聚合函数组合使用单个查询中可以包含多个聚合函数-- 综合统计报表 SELECT COUNT(*) AS total_orders, SUM(amount) AS total_sales, AVG(amount) AS avg_order, MAX(amount) AS max_order, MIN(amount) AS min_order FROM orders WHERE order_date 2023-01-01;在数据仓库建设中这种综合统计可以显著减少查询次数。我建议为常用聚合组合创建视图简化复杂查询。4.2 聚合函数性能优化策略索引优化为GROUP BY和WHERE条件中的列创建合适索引CREATE INDEX idx_dept ON employees(department);减少分组列数GROUP BY的列越多性能开销越大使用EXPLAIN分析检查执行计划优化查询路径EXPLAIN SELECT department, AVG(salary) FROM employees GROUP BY department;考虑使用派生表对大数据集先过滤再聚合SELECT d.department, d.avg_salary FROM ( SELECT department, AVG(salary) AS avg_salary FROM employees WHERE hire_date 2020-01-01 GROUP BY department ) AS d WHERE d.avg_salary 8000;在千万级用户行为分析系统中通过合理使用这些技巧我们将聚合查询性能提升了5倍以上。4.3 窗口函数与聚合函数的结合MySQL 8.0支持窗口函数可以与聚合函数结合实现更灵活的分析-- 计算各部门薪资排名及与平均值的比较 SELECT employee_id, department, salary, AVG(salary) OVER (PARTITION BY department) AS dept_avg, salary - AVG(salary) OVER (PARTITION BY department) AS diff_from_avg FROM employees;这种写法避免了多次子查询在复杂分析场景下性能更好。我在最近的一个BI项目中用窗口函数重构了原有的大量子查询使查询速度提升了70%。