ORDER BY 必须位于 WHERE 之后、LIMIT 之前;支持多字段混合升降序、别名引用及 NULL/字符集排序规则;但是否走索引取决于与 WHERE 条件和联合索引的匹配程度。

ORDER BY 必须写在 WHERE 和 LIMIT 之间
MySQL 的 SELECT 语句中,ORDER BY 的位置有严格要求:它不能出现在 WHERE 之前,也不能放在 LIMIT 之后。否则会报错 ERROR 1064 (42000),提示语法错误。
正确顺序是:SELECT ... FROM ... WHERE ... ORDER BY ... LIMIT ...
- 如果带
GROUP BY,ORDER BY必须在其后(且通常用于对分组结果排序) -
ORDER BY子句可以引用 SELECT 列的别名(如SELECT name AS uname ORDER BY uname),但不能引用未出现在 SELECT 中的非聚合列(除非启用了ONLY_FULL_GROUP_BY以外的 SQL 模式) - 在子查询中使用
ORDER BY时,若不配合LIMIT,MySQL 5.7+ 可能直接忽略该子句——因为子查询结果集本身无序,排序无效
ASC 和 DESC 是显式声明,不是默认行为
ORDER BY col 看似默认升序,其实只是 MySQL 对 ASC 的省略写法;它和 ORDER BY col ASC 完全等价。但这个“默认”只存在于语法层面,不代表执行计划或索引利用上更优。
- NULL 值在排序中总是排在最前(
ASC)或最后(DESC),不受字段类型影响 - 字符串排序依赖列的字符集和校对规则(collation),比如
utf8mb4_0900_as_cs区分大小写,而utf8mb4_general_ci不区分——这会影响'apple'和'Apple'的相对位置 - 多字段排序时,
ORDER BY a ASC, b DESC表示先按a升序,a相同时再按b降序;两个方向可混用,无需统一
ORDER BY 走不上索引的常见原因
即使 col 上有索引,ORDER BY col 也不一定走索引排序。MySQL 是否使用索引做排序(filesort),取决于执行计划是否能复用已有的 B+ 树顺序。
- WHERE 条件用了范围查询(如
WHERE status > 1),则ORDER BY create_time很可能无法复用索引,触发 filesort - 排序字段和 WHERE 字段不在同一联合索引中,或顺序不匹配(例如索引是
(a,b),但写了WHERE b = ? ORDER BY a) - SELECT 中包含非索引字段(尤其是大字段如
TEXT),优化器可能认为回表成本高,改用 sort_buffer + filesort - 可通过
EXPLAIN查看Extra列:出现Using filesort就说明没走索引排序
中文排序要小心 collation 和函数干预
直接 ORDER BY name 对中文字段排序,结果往往是按 Unicode 码点排,不是拼音或笔画顺序,看起来乱序。
- 建表时指定校对规则,如
VARCHAR(50) COLLATE utf8mb4_unicode_ci,能在一定程度上改善拼音排序效果(但仍有局限) - 临时按拼音排序可用
ORDER BY CONVERT(name USING gbk)(依赖系统 GBK 支持)或ORDER BY HEX(name)(不推荐,仅调试) - 生产环境建议在应用层处理中文排序逻辑,或用生成列(generated column)预存拼音字段并建索引,例如:
ALTER TABLE user ADD COLUMN name_pinyin VARCHAR(100) STORED AS (pinyin(name)) INDEX;










