order by必须写在group by之后,因sql执行顺序为from→where→group by→having→select→order by;排序字段须为分组列或聚合结果(如count(*)或其别名),且降序需显式写desc,多字段排序按逗号分隔的优先级从左到右执行。

ORDER BY 必须写在 GROUP BY 之后
很多人写完 GROUP BY 就直接加 ORDER BY,结果报错或排序无效——根本原因是把 ORDER BY 放错了位置。SQL 执行顺序是 FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY,所以对聚合结果排序,ORDER BY 一定得在 GROUP BY 后面、且不能出现在子句中间。
用聚合字段名或别名排序最稳妥
聚合函数(如 COUNT()、SUM()、AVG())产生的列没有原始列名,直接在 ORDER BY 里写 COUNT(*) 虽然多数数据库支持,但可读性差、易出错。更推荐用列别名:
SELECT category, COUNT(*) AS cnt FROM products GROUP BY category ORDER BY cnt DESC;
注意:有些数据库(如 MySQL 5.7 严格模式)不支持在 ORDER BY 中用未出现在 SELECT 列表里的表达式,所以别名是最安全的选择。
DESC 是显式声明,不是默认行为
ORDER BY 默认升序(ASC),降序必须明确写 DESC。漏掉它会导致结果和预期相反,尤其当数据量大时不易察觉。常见错误包括:
- 误以为
GROUP BY本身会按聚合值排序(不会) - 只写
ORDER BY COUNT(*),没加DESC - 在
HAVING后面加ORDER BY,但忘了HAVING不影响排序逻辑
多字段排序要注意优先级和 NULL 处理
如果既要按聚合值降序,又要按分组字段升序(比如相同销量时按品类字母序排),写法是:
ORDER BY COUNT(*) DESC, category ASC
注意两点:一是多个字段用逗号分隔,优先级从左到右;二是 NULL 值默认排在最前(ASC)或最后(DESC),不同数据库行为略有差异(PostgreSQL 和 SQL Server 把 NULL 当最大值,MySQL 默认当最小值)。需要统一控制时,加上 NULLS FIRST 或 NULLS LAST(仅部分数据库支持,如 PostgreSQL)。
聚合后排序看似简单,但实际最容易栽在执行顺序混淆、别名缺失、DESC 遗漏这三处——尤其是线上查数据时临时加 ORDER BY 却没验证结果方向,一不留神就看反了 Top N。











