在MySQL的查询操作中,对结果集进行排序是高频需求,合理运用排序规则可以让返回的数据更符合业务逻辑。无论是简单的数值、时间升序降序,还是特殊的业务自定义排序,都可以通过SQL的排序语法实现。

基础排序语法:ORDER BY
MySQL中使用ORDER BY子句对查询结果进行排序,默认是升序排序,基础语法结构如下:
-- 基础排序语法 SELECT 列名1, 列名2 FROM 表名 ORDER BY 排序列 [ASC|DESC];
其中ASC表示升序(可省略),DESC表示降序。下面通过一个用户表的示例来演示基础排序效果,假设我们有如下用户表user_info:
| id | username | age | create_time |
|---|---|---|---|
| 1 | 张三 | 25 | 2024-03-01 10:00:00 |
| 2 | 李四 | 22 | 2024-03-02 11:00:00 |
| 3 | 王五 | 28 | 2024-03-01 09:00:00 |
升序排序示例
按照用户年龄从小到大排序:
SELECT id, username, age FROM user_info ORDER BY age ASC; -- 等价于 SELECT id, username, age FROM user_info ORDER BY age;
返回结果会按照22、25、28的顺序展示用户数据。
降序排序示例
按照用户注册时间从新到旧排序:
SELECT id, username, create_time FROM user_info ORDER BY create_time DESC;
返回结果会优先展示2024-03-02 11:00:00的李四,再展示其他用户。
多列排序
如果需要先按一个字段排序,该字段值相同时再按另一个字段排序,可以在ORDER BY后加多个排序字段:
-- 先按年龄升序,年龄相同再按注册时间降序 SELECT id, username, age, create_time FROM user_info ORDER BY age ASC, create_time DESC;
自定义排序规则实现
有时候基础的升序降序无法满足业务需求,比如需要按照指定的状态顺序展示数据,例如订单状态需要按照待支付、待发货、待收货、已完成、已取消的顺序展示,而不是按照状态编码的大小排序,这时候就需要自定义排序规则。
使用FIELD函数实现自定义排序
MySQL提供了FIELD()函数,可以指定字段的排序优先级,语法为FIELD(字段名, 值1, 值2, 值3...),函数会返回字段值在参数列表中的位置,位置越靠前排序越靠前。
假设订单表order_info的status字段取值为:1待支付、2待发货、3待收货、4已完成、5已取消,需要按照业务指定顺序排序:
SELECT id, order_no, status FROM order_info ORDER BY FIELD(status, 1, 2, 3, 4, 5);
如果需要调整顺序,比如把已取消的订单放到最前面,只需要调整FIELD函数的参数顺序即可:
SELECT id, order_no, status FROM order_info ORDER BY FIELD(status, 5, 1, 2, 3, 4);
使用CASE WHEN实现复杂自定义排序
如果自定义排序的规则更复杂,比如需要根据多个条件组合排序,可以使用CASE WHEN语句生成排序权重,再按照权重排序:
SELECT id, username, age, vip_level FROM user_info ORDER BY CASE WHEN vip_level = '钻石' THEN 1 WHEN vip_level = '黄金' THEN 2 WHEN vip_level = '普通' THEN 3 ELSE 4 END ASC, age DESC;
上面的语句会先按照VIP等级钻石、黄金、普通的顺序排序,同等级的用户再按照年龄从大到小排序。
排序注意事项
- 如果排序的字段没有索引,MySQL会对全表数据进行排序,数据量大的时候会有性能问题,建议对常用排序字段建立索引。
ORDER BY子句要放在WHERE子句之后,LIMIT子句之前。- 对字符串类型字段排序时,默认按照字符集的校对规则排序,中文排序可能需要指定对应的校对规则,比如
ORDER BY username COLLATE utf8mb4_chinese_ci。 FIELD()函数如果字段值不在参数列表中,会返回0,所以不在指定范围内的值会排在最前面。
排序操作会消耗一定的数据库资源,在编写SQL时要根据实际需求选择合适的排序方式,避免不必要的性能损耗。