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

如何使用 MySQL 做数据统计:从入门到高阶实战

摘要:数据统计是后端开发和数据分析的高频需求。是用代码在内存里算,还是让数据库算?本文深入讲解 MySQL 统计分析的核心能力,涵盖聚合函数、分组汇总、去重计数、窗口函数以及性能优化策略,帮你搞定 90% 的数据统计场景。


一、 前言:别把计算压力扔给应用层

很多初级开发在做统计时,习惯把数据全查出来,在 Java/Python/Go 代码里循环计算:

# ❌ 错误示范:把 100 万行数据拉到内存里算rows=db.query("SELECT * FROM orders WHERE status='paid'")total=0forrowinrows:total+=row.amount

这种做法不仅慢,还会把应用服务器的内存打爆。MySQL 内置了强大的统计函数,让数据在磁盘端就完成计算,只返回结果集,这才是正确姿势。


二、 基础篇:核心聚合函数

这是统计的基石,必须熟练掌握。

1. COUNT 系列:数数的艺术

  • COUNT(*):统计行数(不关心 NULL,性能最优)。
  • COUNT(field):统计指定字段非 NULL 的行数。
  • COUNT(DISTINCT field):统计去重后的数量。

⚠️ 坑点SELECT COUNT(*) FROM table在 InnoDB 中其实很快(不像 MyISAM 那样存了元数据,但 InnoDB 会走最小的二级索引),千万别为了加速而用COUNT(1),优化器会自动把它们变成一样的执行计划。

2. SUM / AVG / MAX / MIN

最基础的求和与极值。

-- 统计近 7 天的总销售额和平均客单价SELECTSUM(amount)astotal_sales,AVG(amount)asavg_price,MAX(create_time)aslast_order_timeFROMordersWHEREcreate_time>NOW()-INTERVAL7DAY;

三、 进阶篇:分组与多维分析

单看总数没意义,我们需要按维度拆解。

1. GROUP BY:按维度切分

-- 按城市统计用户数SELECTcity,COUNT(*)FROMusersGROUPBYcity;

优化技巧GROUP BY的字段必须建立索引,否则会产生临时表(Using temporary)和文件排序(Using filesort),性能极差。

2. WITH ROLLUP:小计与总计

如果你需要“各城市小计 + 全国总计”,不需要写两条 SQL,用WITH ROLLUP一把梭:

SELECTcity,COUNT(*)FROMusersGROUPBYcityWITH ROLLUP;
  • 结果会多一行NULL,这就是总计。

3. GROUPING SETS:多维度交叉

假设你要同时看“按性别统计”和“按年龄统计”,传统写法要UNION ALL,现在可以用:

SELECTgender,age_group,COUNT(*)FROMusersGROUPBYGROUPING SETS((gender),(age_group));

四、 高阶篇:窗口函数(MySQL 8.0+)

这是现代 SQL 的大杀器,能解决“排名”、“累计”、“移动平均”等难题,无需自连接

1. 排名问题:谁是 Top N?

-- 查询每个部门工资前 3 名的员工(允许并列)SELECTname,department,salary,DENSE_RANK()OVER(PARTITIONBYdepartmentORDERBYsalaryDESC)asrankingFROMemployees;
  • ROW_NUMBER():不重复排名 (1, 2, 3)
  • RANK():跳跃排名 (1, 1, 3)
  • DENSE_RANK():连续排名 (1, 1, 2)

2. 累计与移动平均

-- 计算每日销售额及近 3 天移动平均(MA3)SELECTdate,sales,AVG(sales)OVER(ORDERBYdateROWSBETWEEN2PRECEDINGANDCURRENTROW)asmoving_avg_3dFROMdaily_report;

3. 同比/环比

利用LAG()函数取上一行的值:

SELECTdate,sales,LAG(sales,1)OVER(ORDERBYdate)asprev_day_sales,(sales-LAG(sales,1)OVER(ORDERBYdate))/LAG(sales,1)OVER(ORDERBYdate)*100asgrowth_rateFROMdaily_report;

五、 实战篇:时间序列统计

做报表时,最怕数据“断档”。比如统计最近 30 天的日活,如果某天没数据,SQL 不会返回 0,而是直接跳过这一天。

解决方案:补全时间轴

MySQL 本身没有生成序列的函数(不像 PostgreSQL 的generate_series),我们需要用“数字表”或者递归 CTE 来制造一个连续的时间序列,然后左连接业务表。

-- 1. 生成连续日期(递归 CTE,MySQL 8.0+)WITHRECURSIVE date_seriesAS(SELECTCURDATE()-INTERVAL29DAYasdtUNIONALLSELECTdt+INTERVAL1DAYFROMdate_seriesWHEREdt<CURDATE())-- 2. 左连接业务表,用 IFNULL 补 0SELECTd.dt,COUNT(o.id)asorder_count,-- 这里统计的是左连接后的非空行IFNULL(COUNT(o.id),0)asreal_count-- 更严谨的写法其实是 SUM(CASE WHEN o.id IS NOT NULL THEN 1 ELSE 0 END)FROMdate_series dLEFTJOINorders oONDATE(o.create_time)=d.dtGROUPBYd.dtORDERBYd.dt;

注:如果是低版本 MySQL,需要建一张辅助的数字表(Numbers Table)。


六、 性能优化:让统计飞起来

统计查询通常涉及全表扫描或大范围扫描,如何优化?

  1. 覆盖索引(Covering Index)
    如果统计只涉及索引列,MySQL 就不需要回表查数据行。

    -- 假设有索引 idx_city (city)SELECTcity,COUNT(*)FROMusersGROUPBYcity;-- 极快,只扫索引
  2. **避免 SELECT ***
    统计时只查需要的字段,减少网络传输和内存开销。

  3. 近似计算
    如果不需要 100% 精确(如 UV 统计),用APPROX_DISTINCT(基于 HyperLogLog 算法)比COUNT(DISTINCT)快 10 倍以上,且内存占用极小。

    SELECTAPPROX_DISTINCT(user_id)FROMlogs;
  4. 分表/分库/OLAP

    • 如果单表数据量过亿,统计压力大,考虑分库分表。
    • 如果统计逻辑极其复杂(多表关联、Ad-hoc 查询),不要死磕 MySQL。将数据同步到ClickHouse、Doris 或 TiDB这类 OLAP 数据库,查询速度能提升 10-100 倍。

七、 总结:统计函数速查表

需求场景推荐函数/语法备注
简单计数/求和COUNT,SUM,AVG基础中的基础
分组统计GROUP BY必须带索引
多级汇总WITH ROLLUP替代多次查询
排名/TopNRANK(),DENSE_RANK()窗口函数
累计/移动平均SUM() OVER (... ROWS BETWEEN)窗口函数
同比/环比LAG(),LEAD()窗口函数
近似去重APPROX_DISTINCT大数据量首选
时间轴补全递归 CTE + Left Join解决数据断层

最后的一句话
MySQL 不仅是一个 OLTP(事务处理)数据库,掌握好上述统计技巧,它也能胜任轻量级的 OLAP(分析)工作。但如果你的业务是“双十一大屏实时监控”或者“每天跑几百个复杂报表”,请果断上 ClickHouse。


如果你觉得这篇文章有帮助,欢迎点赞、收藏并分享给你的开发伙伴!

http://www.jsqmd.com/news/439470/

相关文章:

  • Avalonia 适配Win7
  • Flutter 三方库 login_client 的鸿蒙化适配指南 - 打造工业级安全登录、OAuth2 自动化鉴权、鸿蒙级身份守门员
  • ubuntu24.04 LTS 安装 riscv32 预编译工具链
  • 2026年3月胶水检测公司最新推荐,粘接强度成分解析 - 品牌鉴赏师
  • 伊犁民宿设计装修费用大概多少钱,新疆匠之初装饰设计收费合理吗? - mypinpai
  • 当前主流AI大模型
  • 分析2026年好用的轻小型起重机定制品牌排名,有你心仪的吗 - 工业推荐榜
  • 目标检测数据集 - 卫星图像游泳池汽车检测数据集下载
  • st-linkv2 stm32f103的能在stm32f407vet6上使用吗? 烧录之类的
  • 2026年南京酒店酒窖定制地址探寻,哪个比较靠谱 - myqiye
  • 用go写一个微服务gPRC为主RESTful为辅
  • Flutter 三方库 posix 的鸿蒙化适配指南 - 掌控底层系统调用、文件权限管理实战、鸿蒙级系统级工具专家
  • 2026年3月喷丝板清洗机厂家推荐,专业制造与品牌保障口碑之选 - 品牌鉴赏师
  • 北京工装设计师推荐:易楷东设计师 - 余小铁
  • 自动化立体仓库核心品牌深度评测:技术与场景适配性解析 - 品牌种草官
  • 2026年3月饭店厨房设备厂家最新推荐,实用省心性价比高 - 品牌鉴赏师
  • 2026年成都酒柜定制厂家推荐:聚焦环保健康与本地化服务的实力之选 - 深度智识库
  • 2026市面上新型撤离舱品牌哪家强?这份排行别错过,撤离舱厂家口碑排行榜优选实力品牌 - 品牌推荐师
  • 2026低空安全防护之选 五家反无人机企业助力空域守护 - 深度智识库
  • 【盘点汇总】哪个厂家的移动转运料仓/中转料仓/周转料仓质量好? - 品牌推荐大师
  • 2026年3月通过式超声波清洗机厂家推荐,专业制造与品牌保障口碑之选 - 品牌鉴赏师
  • 热机械分析仪哪家好?从温度精度到载荷系统,这篇全讲透了! - 品牌推荐大师1
  • 2026年3月东莞独立站公司推荐榜:甄选企业实测解析 - 品牌鉴赏师
  • OpenClaw 的实现逻辑与本质;流式传输形态;
  • Dante记录
  • PbootCMS提示错误信息“未检测到您服务器环境的sqlite3数据库扩展…”
  • 实用指南:04 - SVM核心数据结构详解
  • 2026年成都榻榻米定制厂家哪家好?本地优选指南 - 深度智识库
  • 6.ethercat主站芯片
  • 2026送礼首选!5款真实睡眠仪排名,双龙脉小黑钥直击熬夜加班痛点 - 速递信息