最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
SQL中同时使用GROUP BY与ORDER BY要注意什么?
时间:2026-07-21 09:45:59 编辑:袖梨 来源:一聚教程网
GROUP BY 和 ORDER BY 不能直接组合实现“每组取最新/最高一条”,因 GROUP BY 先执行且只保留每组首行,ORDER BY 仅对其排序;正确方案是窗口函数或关联子查询。
GROUP BY 和 ORDER BY 不能随便连用,否则查出来的不是你想要的那条记录——尤其是想“每组取最新/最高的一条”时,几乎必然出错。
ORDER BY 字段必须在 GROUP BY 列表里或套聚合函数
MySQL 5.7+ 默认开启 ONLY_FULL_GROUP_BY,只要 ORDER BY 后的字段没出现在 GROUP BY 子句中,也没被 MAX()、COUNT() 等包裹,就会直接报错:Expression #1 of ORDER BY clause is not in GROUP BY clause。
- 错误写法:
SELECT examId, score FROM ko_monthly_exam_history GROUP BY examId ORDER BY score DESC(score既没分组也没聚合) - 正确写法(聚合兜底):
SELECT examId, MAX(score) AS score FROM ko_monthly_exam_history GROUP BY examId ORDER BY score DESC - 正确写法(扩展分组):
SELECT examId, score FROM ko_monthly_exam_history GROUP BY examId, score ORDER BY score DESC(但语义已变,不再是“每组一条”,而是去重组合)
GROUP BY 后的 ORDER BY 不会帮你挑组内最大/最新记录
GROUP BY 先执行,只保留每组“第一行”(物理顺序或引擎默认行为),ORDER BY 对的是这“一行”的字段再排一次序,跟组内其他数据完全无关。
- 现象:
SELECT id, examId, score FROM t GROUP BY examId ORDER BY score DESC返回的id很可能对应的是该组低分记录,不是最高分那条 - 根本原因:执行顺序是
FROM → WHERE → GROUP BY → SELECT → ORDER BY,ORDER BY根本看不到组内全量数据 - 别信“子查询先
ORDER BY再GROUP BY”:MySQL 5.7+ 优化器会丢弃子查询里的ORDER BY,除非加LIMIT 999999999强制保留(不推荐)
真正要取每组最新/最高记录,得用窗口函数或关联子查询
想按 examId 分组,取每组 score 最高且 time 最新的那条完整记录,必须跳出 GROUP BY 的限制。
- MySQL 8.0+ 推荐窗口函数:
SELECT * FROM (SELECT *, ROW_NUMBER() OVER (PARTITION BY examId ORDER BY score DESC, time DESC) AS rn FROM ko_monthly_exam_history) t WHERE t.rn = 1 - 兼容老版本用关联子查询:
SELECT t1.* FROM ko_monthly_exam_history t1 WHERE t1.id = (SELECT id FROM ko_monthly_exam_history t2 WHERE t2.examId = t1.examId ORDER BY score DESC, time DESC LIMIT 1) - 注意子查询加
LIMIT的坑:SELECT * FROM (SELECT * FROM t ORDER BY score DESC LIMIT 1000) s GROUP BY examId可能漏掉没进前 1000 的examId,LIMIT必须放最外层
ORDER BY 字段没索引会导致排序失效
即使语法合法、逻辑正确,如果 ORDER BY 字段没索引,MySQL 会走 Using filesort,结果顺序看似随机,性能也差。
- 用
EXPLAIN看Extra列:出现Using filesort就说明没走索引排序 -
ORDER BY字段尽量落在驱动表(FROM后第一张表)上 - 复合索引更稳妥:比如常按
examId分组、再按MAX(time)排序,建INDEX idx_exam_time (examId, time) - 别写
ORDER BY 2这类位置引用——字段一增减就全乱
最容易被忽略的点是:你以为 GROUP BY + ORDER BY 能取每组最优记录,其实它只负责把组排个序;真正筛选组内数据,得靠窗口函数、子查询或业务层二次处理。别让 ONLY_FULL_GROUP_BY 报错把你骗过去——报错只是表象,逻辑错才是根因。
相关文章
- 梦幻西游凌波城109级装备搭配 07-28
- 三角洲行动仿星器控制室位于何处 07-28
- 三角洲行动压水堆服务器室在何处 07-28
- 三角洲行动铁路通道何处 07-28
- 三角洲行动托卡马克数据中心在哪 07-28
- 三角洲行动后处理厂机房何在 07-28