ORDER BY 默认是升序(ASC),这是SQL标准明确规定的行为,无需显式写出ASC关键字;若需降序则必须明确指定DESC。

ORDER BY 默认是升序还是降序?
ORDER BY 默认按升序(ASC)排列,但这个关键字可以省略。如果你没写 DESC,数据库就当你是要升序——不是靠猜,是 SQL 标准明确规定的。很多新手在调试时发现结果“不对”,其实是误以为默认是降序,或者漏看了字段值本身是否真有大小差异。
实操建议:
- 显式写出
ASC或DESC,避免团队协作或后期维护时产生歧义 - 字符串排序依赖当前 collation,比如
'apple'和'Apple'的先后顺序可能因大小写敏感设置而不同 - NULL 值在排序中通常排在最前(升序)或最后(降序),但 PostgreSQL 和 MySQL 行为略有差异,不能假设一致
多个字段排序时,ORDER BY 的执行顺序怎么理解?
ORDER BY 后面的字段是从左到右逐级生效的:先按第一个字段分组排序,相同值的记录再按第二个字段排,以此类推。这不是“同时比较”,而是嵌套优先级。
常见错误现象:写成 ORDER BY status, created_at DESC,本意是想让每个 status 组内按时间倒序,结果却发现所有记录都按 created_at 降序了——因为 DESC 只作用于紧邻的 created_at,而 status 仍是默认升序。
正确写法应明确指定:ORDER BY status ASC, created_at DESC
使用场景举例:查订单列表,优先看订单状态(如 'shipped' 排前面),同状态的按发货时间最新在前。
ORDER BY 能用列别名、表达式或数字序号吗?
可以,但兼容性不一。MySQL 和 PostgreSQL 支持列别名和位置序号(如 ORDER BY 2 表示按 SELECT 列表中第 2 个字段排),SQL Server 也支持别名;但 SQLite 对位置序号的支持有限制,Oracle 则完全不支持位置序号。
实操建议:
- 优先用字段名或别名,语义清晰且移植性强
- 避免用数字序号,尤其在 SELECT 中有计算字段或
*时,极易因字段顺序变动导致逻辑错乱 - 表达式如
ORDER BY UPPER(name)是合法的,但可能无法利用索引,影响性能
为什么加了 ORDER BY 还是得不到稳定排序?
最常见原因是排序字段存在重复值,而你又没提供足够区分度的次级排序条件。比如按 score 降序,但多条记录分数相同,数据库返回顺序就取决于底层存储或执行计划,每次查询可能不一样。
另一个容易被忽略的点:如果查询带了 LIMIT 或 OFFSET,但没配稳定排序,分页结果可能出现重复或丢失(俗称“幻读分页”)。
解决方法很简单:在 ORDER BY 末尾补一个唯一字段,通常是主键:ORDER BY score DESC, id ASC。这样即使分数一样,也能保证每次顺序绝对一致。
性能提示:复合排序字段越多,越难命中索引。如果高频使用 ORDER BY a DESC, b ASC,建索引时得注意方向一致性(MySQL 8.0+ 支持降序索引,老版本只存升序,DESC 字段会走 filesort)。


















