正确:mysql中使用group by时,select子句只能包含分组字段或聚合函数,否则在严格模式下会因逻辑冲突报错(如error 1055),这是为防止返回不确定结果而设的sql标准强制要求。

SELECT后面只能放聚合函数或GROUP BY字段
直接写 SELECT name, AVG(score) 会报错,不是语法错了,而是逻辑冲突:数据库不知道该挑哪个 name 和这组平均分配对。你得明确告诉它“按什么分组”,比如按 class 分组,那 SELECT class, AVG(score) 就合法。
常见错误现象:ERROR 1055 (SQL_MODE=only_full_group_by) —— 这不是bug,是MySQL在帮你防逻辑混乱。
- 如果没用
GROUP BY,SELECT里所有非聚合列都会被拒绝 -
GROUP BY字段必须和SELECT中的非聚合列完全一致(不能只写前缀或别名) - 想保留原始行信息?别硬套聚合函数,考虑用窗口函数
AVG() OVER (PARTITION BY class)
COUNT(*) 和 COUNT(列名) 的 NULL 处理差异很大
COUNT(*) 统计所有行,哪怕整行都是 NULL;COUNT(score) 只统计 score 列非空的行。这点在清洗数据时特别关键——比如你想知道“有多少人交了作业”,就得用 COUNT(submit_time),而不是 COUNT(*)。
-
COUNT(DISTINCT user_id)能去重计数,但性能开销大,大表慎用 -
COUNT(1)和COUNT(*)效果一样,别信“更快”的传言,现代优化器基本无差别 - 如果列允许
NULL,又想统计“理论上应有几条”,必须用COUNT(*),不能靠COUNT(列名)推算
AVG、SUM、MIN、MAX 自动跳过 NULL,但结果可能是 NULL
哪怕只有一行有效数据,AVG() 也能算出值;但如果整组全是 NULL,它就返回 NULL,不是 0。很多业务逻辑崩在这里——比如前端把 NULL 当成 0 渲染,导致“平均分显示为0”这种误导。
- 保险做法:用
COALESCE(AVG(score), 0)显式转成 0 -
SUM()对空组也返回NULL,不是 0;MIN()/MAX()同理 -
AVG()只接受数值类型,传字符串会报错,别指望它自动转类型
GROUP BY 后加 HAVING 筛选,别用 WHERE
WHERE 是在分组前过滤行,HAVING 才是用来筛分组结果的。比如“查平均分超85的班级”,必须写 HAVING AVG(score) > 85,写在 WHERE 里会直接报错。
-
HAVING可以引用SELECT中的聚合别名,比如SELECT AVG(score) AS avg_s FROM t GROUP BY class HAVING avg_s > 85 - 别在
HAVING里写非聚合字段,除非它也在GROUP BY里 - 性能上,先
WHERE再GROUP BY再HAVING是最优顺序,别颠倒
GROUP BY 还报错,其实只是漏掉了 SELECT 里的对应字段,或者误把聚合结果当普通列用了。











