mysql如何进行结果排序_mysql order by升降序

5次阅读

order by 默认是升序(asc),例如 order by created_at 实际等价于 order by created_at asc;需降序时必须显式写 desc,如 order by created_at desc。

mysql如何进行结果排序_mysql order by升降序

ORDER BY 默认是升序还是降序?

mysqlORDER BY 默认按**升序(ASC)**排列,不是降序。很多人写完 ORDER BY created_at 就默认是“最新在前”,结果发现最早的数据排第一——这就是踩了默认 ASC 的坑。

实操建议:

  • 只要需要“时间倒序”“金额从高到低”这类场景,必须显式写 DESC,比如 ORDER BY created_at DESC
  • ASC 可省略,但 DESC 不能省;省略不等于不存在,只是语法允许你偷懒
  • 多个字段混合排序时,每个字段的升降序要单独指定:ORDER BY status ASC, updated_at DESC

NULL 值在 ORDER BY 中怎么排?

MySQL 把 NULL 当作“最小值”处理:在 ASC 时排最前,在 DESC 时排最后。这和 postgresqloracle 不同(它们默认把 NULL 当最大值),容易在迁移或对比查询结果时出偏差。

常见错误现象:

  • ORDER BY score DESC 查排行榜,结果 NULL 分数的用户总在底部,挤走了真实低分用户
  • 前端分页时第一页突然冒出一空数据,就是 NULL 被当最小值顶上来了

解决办法:

  • IS NULL 显式控制位置,例如 ORDER BY score IS NULL, score DESCNULL 排最后
  • 或者提前用 COALESCE(score, -1) 填充,默认值要确保不影响业务逻辑

ORDER BY 字段没索引会多慢?

如果 ORDER BY 的字段没索引,MySQL 很可能触发 using filesort——不是真去磁盘排序,而是在内存或临时文件里做二次排序,性能断崖式下跌。

使用场景判断:

  • 单表小数据量(
  • 配合 LIMIT 也不保险:即使只查 10 条,MySQL 仍需先把全表排完再截取
  • WHERE + ORDER BY 共用复合索引才高效,比如 WHERE status = 'active' ORDER BY created_at DESC,索引应建为 (status, created_at)

检查方法:执行 EXPLAIN SELECT ... ORDER BY ...,看 Extra 列是否含 Using filesort

中文字段排序为什么乱?

直接 ORDER BY name 对中文列排序,结果可能是“张三”在“阿猫”前面——因为默认按字符编码(如 utf8mb4_bin)逐字节比,不是按拼音或笔画。

原因和选择:

  • utf8mb4_general_ci 已废弃,不推荐;utf8mb4_unicode_ci 按 Unicode 排序,对中文支持一般
  • 真正靠谱的是 utf8mb4_pinyin_ci(需安装插件)或 MySQL 8.0+ 的 utf8mb4_0900_as_cs(区分大小写+按字母序),但都不原生支持拼音首字母
  • 最稳的方案:加一个生成列存拼音首字母,比如 first_pinyin CHAR(1) STORED AS (LEFT(UPPER(pinyin(name)), 1)),再给它建索引

临时应急可用 ORDER BY CONVERT(name USING gbk),但 GBK 编码有兼容风险,别上生产。

排序逻辑一旦涉及语言习惯,就不再是纯 SQL 问题,得结合业务预期、字符集、索引和可维护性一起权衡。最容易被忽略的,其实是开发时用测试数据看不出问题,等上线百万级中文名一排序,全乱套。

text=ZqhQzanResources