如何用SQL GROUP BY进行分组统计

P粉602998670

P粉602998670

2026-07-31

584人浏览

原创

group by本身不产生统计结果,必须配合count、sum、avg等聚合函数才真正统计;单独分组时select字段若漏掉聚合或分组字段,99%会报错,根本原因是数据库无法确定同一分组内多个不同值应返回哪一个。

如何用sql group by进行分组统计

直接说结论:GROUP BY 本身不产生统计结果,必须配合 COUNTSUMAVG 等聚合函数才真正“统计”;单独写 GROUP BY 只是分组动作,SELECT 列中漏掉聚合或分组字段,99% 会报错。

GROUP BY 后 SELECT 字段为什么总报错?

错误现象:ERROR: column "name" must appear in the GROUP BY clause or be used in an aggregate function(PostgreSQL/SQL Server)或 MySQL 的 Expression #2 of SELECT list is not in GROUP BY clause

  • 根本原因:数据库不知道你想要哪一行的 name——每个分组可能有几十条记录,name 值各不相同
  • 合法写法只有两种:SELECT dept, COUNT(*) FROM emp GROUP BY dept(只选分组字段+聚合);或 SELECT dept, MAX(name), COUNT(*) FROM emp GROUP BY dept(非分组字段必须用聚合包裹)
  • 别依赖 ANY_VALUE(name)(MySQL 特有)或低版本 MySQL 的“宽容模式”,它返回值不可复现,跨库迁移必崩
  • 字符串字段如 email 大小写不一致、前后空格未清理,会导致同一用户被拆成多组——先 GROUP BY TRIM(LOWER(email)) 再统计

COUNT(*) 和 COUNT(列名) 统计结果为什么差很多?

不是性能问题,是语义差异:前者数行,后者数非 NULL 值。

小羊标书
小羊标书

一键生成百页标书,让投标更简单高效

下载
  • COUNT(*) 统计该组全部行数,包括所有字段为 NULL 的行;COUNT(email) 只统计 email IS NOT NULL 的行
  • 常见误用:SELECT dept, COUNT(id) FROM emp GROUP BY dept —— 若 id 允许为 NULL,结果就少于实际人数
  • 想补全缺失数?用 COUNT(*) - COUNT(email) 直接得出每组缺邮箱的人数
  • COUNT(DISTINCT email) 是另一回事:它去重后计数,不是“有邮箱的人数”,除非你真要算不同邮箱个数

想看每组最新一条记录,能用 GROUP BY + MAX() 拼吗?

不能。这是最隐蔽也最危险的误用——MAX(created_at)MAX(status) 很可能来自不同行,拼出来的结果逻辑上不存在。

  • 错误示例:SELECT order_id, MAX(status), MAX(amount), MAX(created_at) FROM orders GROUP BY order_id
  • 正确做法是用窗口函数:ROW_NUMBER() OVER (PARTITION BY order_id ORDER BY created_at DESC) 标记序号,再 WHERE rn = 1
  • 如果数据库不支持窗口函数(如旧版 SQLite),改用关联子查询或 JOIN + MAX(created_at) 先取时间,再回连原表捞整行
  • 硬套 GROUP BY 还可能引发“分组爆炸”:比如对毫秒级时间戳分组,每行都成一组,COUNT(*) 等于原表行数,完全失去统计意义

WHERE 和 HAVING 混用时,为什么结果总不对?

它们作用阶段完全不同:一个筛原始行,一个筛分组后结果。写反了不是慢一点,而是查不到或语法报错。

  • WHEREGROUP BY 之前执行——例如 WHERE status = 'active' 先剔除无效数据,再分组,性能更好
  • HAVING 在分组之后执行——例如 HAVING COUNT(*) > 5 是筛选“组内行数超 5 的部门”,不能写成 WHERE COUNT(*) > 5(语法错误)
  • 典型错误组合:SELECT dept, AVG(salary) FROM emp GROUP BY dept WHERE AVG(salary) > 8000 → 报错,WHERE 阶段 AVG() 还没算出来
  • 想同时满足“2023 年后入职”且“平均薪资 > 8000”,必须两层:先 WHERE hire_date > '2023-01-01',再 HAVING AVG(salary) > 8000

最容易被忽略的点:NULL 在分组中是合法值,且所有 NULL 自动归为同一组——这看起来合理,但业务上它可能代表“未知”“未填写”“已注销”,混在一起统计会掩盖真实问题。需要时,提前用 COALESCE(dept, 'unknown')CASE WHEN dept IS NULL THEN 'unassigned' ELSE dept END 处理。

阿姐鼓3相关攻略
《阿姐鼓3偃师传》全章节通关攻略大全 《阿姐鼓3偃师传》第一章问医攻略 《阿姐鼓3偃师传》第一章通关攻略图文
《阿姐鼓3偃师传》第四章通关攻略图文 《阿姐鼓3偃师传》第二章通关攻略图文 《阿姐鼓3》游戏攻略全部图解
《阿姐鼓3》第三章攻略详情 《阿姐鼓3》第五章攻略详情 MySQL中如何使用UNION ALL优化查询?
SQL中GROUP BY如何排除特定分组条件? SQL中WHERE和HAVING有什么区别 如何用SQL聚合函数统计数据
SQL如何查询订单数超过指定数量的客户 SQL如何使用聚合函数SUM对分组数据进行求和? Java 中 MySQL 怎么利用延迟关联技术优化超大位移量 limit offset 的查询速度
SQL中如何在HAVING条件里使用子查询 如何用SQL找出分组数量排名前10的数据 SQL中WHERE和HAVING该如何选择?
SQL如何通过GROUP BY识别僵尸用户?

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

2023.10.12

2450

8

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.10.27

448

4

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

2024.02.23

614

5

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

3966

10

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

2024.03.06

1324

4

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

2024.04.07

3540

11

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

2024.04.29

3489

6

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

641

5

sql中删除一列的命令是什么
sql中删除一列的命令是什么

在sql中,使用alter table语句可以删除一列,语法为:alter table table_name drop column column_name。想了解更多sql的相关内容,可以阅读本专题下面的文章。

2024.04.29

526

5

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
热门推荐
/
最新课程
phpStudy极速入门视频教程
phpStudy极速入门视频教程

共6课时 | 54.4万人学习

独孤九贱(4)_PHP视频教程
独孤九贱(4)_PHP视频教程

共89课时 | 131.8万人学习