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;ORDER BY 的真正复杂点不在语法,而在它和索引、字符集、执行计划之间的隐式耦合。很多“明明加了索引却不走”的问题,根源都在排序字段与 WHERE 条件、索引定义三者之间的对齐关系上。
