乐途乐途
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
主页
  • 计算机基础

    • TCP/IP协议
    • Linux命令
    • HTTP协议
  • 数据库

    • SQL
    • MySQL 5.7
  • 编程语言

    • C语言
    • Python2
    • Python3
  • 数据格式

    • JSON
    • XML
  • 认证与安全

    • JWT
  • 工具

    • Markdown
  • Git

    • GitFlow
  • Quartz

    • Quartz
  • Java

    • MyBatis
    • Spring
    • Spring MVC
    • Maven 入门
    • Maven 进阶
    • Java 设计模式
  • 缓存

    • Redis
联系
阿里云
  • 学习路径
  • 第1章 数据库基础与安装

    • MySQL 简介
    • MySQL 5.6 到 5.7 到 8.0 关键差异速查
    • 安装 MySQL 5.7
    • 连接与断开服务器
    • 创建数据库
    • 创建数据表
    • 数据库与数据表
    • 加载数据
    • 获取数据库信息
    • 批处理模式
    • SHOW 语句汇总
    • FLUSH 与 RESET 语句
    • my.cnf 核心参数
    • 字符集与排序规则
  • 第2章 SQL基础查询

    • SELECT
    • WHERE
    • ORDER BY
    • LIMIT
    • COUNT
    • 聚合函数
    • 比较运算符
    • 逻辑运算符
    • 算术运算符
    • 模式匹配
    • NULL 值处理
    • UPDATE
    • DELETE
    • REPLACE
    • SELECT INTO
  • 第3章 数据类型与运算符

    • 数值类型
    • 字符串类型
    • 日期时间类型
    • BIT 类型
    • ENUM 类型
    • SET 类型
    • JSON 类型
    • 类型转换
  • 第4章 函数与表达式

    • 字符串函数
    • 数值函数
    • 日期函数
    • 全文检索函数
  • 第5章 高级查询与子查询

    • JOIN
    • 子查询
    • UNION
    • GROUP BY
    • HAVING
    • DISTINCT
  • 第6章 表与索引

    • 数据定义语言
    • 修改表结构
    • 视图
    • 修改视图与检查选项
    • 外键
    • 索引
    • 唯一索引
    • 复合索引
    • 存储引擎对比
    • 分区表
    • 第一范式与第二范式
    • 第三范式与 BC 范式
    • 反范式设计
  • 第7章 存储过程与函数

    • 存储过程
    • 存储函数
    • 变量
    • 流程控制
    • 游标
    • 预处理语句
  • 第8章 事务与锁

    • 事务
    • 事务隔离级别
    • 锁机制
    • MVCC
    • 死锁专题分析
    • LOCK TABLES
    • XA 事务
  • 第9章 用户管理与安全

    • 用户管理
    • 权限管理
    • 角色
    • SQL 注入防范
  • 第10章 性能优化入门

    • 执行计划
    • 索引优化
    • 查询优化
    • 查询优化器提示
    • 慢查询日志
    • InnoDB 深入机制
    • InnoDB 专项优化
    • Performance Schema
    • sys Schema
  • 第11章 复制与高可用

    • 主从复制原理
    • 半同步复制配置
    • binlog 开启与 point-in-time 恢复
    • mysqldump 全库备份
    • mysqldump 单表与条件备份
    • mysqldump 恢复与导入
    • xtrabackup 全量热备
    • xtrabackup 准备与恢复
    • xtrabackup 增量与流式备份
  • 第12章 触发器与事件

    • 触发器
    • 事件调度器
  • 参考

    • MySQL 5.7 专业术语大全
    • MySQL 5.7 关键字与保留字大全

ORDER BY

导学

数据在表中的物理存储顺序是不可预测的。如果你需要按绩效分高低、姓名字母顺序来展示结果,就必须使用 ORDER BY。

定义

ORDER BY:对查询结果集按指定列进行排序。默认升序(ASC),可显式指定降序(DESC)。支持多列排序,按列的顺序依次比较。

核心语法

SELECT 列 FROM 表
ORDER BY 列1 [ASC|DESC], 列2 [ASC|DESC], ...;

演示数据准备

DROP TABLE IF EXISTS employees;

CREATE TABLE employees (
    emp_id INT PRIMARY KEY AUTO_INCREMENT,
    emp_name VARCHAR(20),
    dept VARCHAR(20),
    score DECIMAL(5,2)
);

INSERT INTO employees (emp_name, dept, score) VALUES
('大翔', '技术部', 100),
('白歌', '技术部', NULL);

当前 employees 表中的完整数据如下:

emp_idemp_namedeptscore
1大翔技术部100
2白歌技术部NULL

SQL 示例

场景一:单列升序排序(默认)

当前数据状态:见上文 employees 表完整数据。

执行语句:

SELECT emp_name, emp_id FROM employees
ORDER BY emp_id;
-- 等价于
-- ORDER BY emp_id ASC;

操作后结果:

emp_nameemp_id
大翔1
白歌2

结果解读:按 emp_id 从小到大升序排列。不指定 ASC 或 DESC 时,默认是 ASC(升序)。

场景二:单列降序排序

当前数据状态:见上文 employees 表完整数据。

执行语句:

SELECT emp_name, score FROM employees
ORDER BY score DESC;

操作后结果:

emp_namescore
大翔100
白歌NULL

结果解读:按 score 从高到低降序排列。注意 NULL 在降序时排在最后面(MySQL 5.7 默认行为)。

场景三:多列排序

当前数据状态:见上文 employees 表完整数据。

执行语句:

SELECT dept, emp_name, score FROM employees
ORDER BY dept ASC, score DESC;

操作后结果:

deptemp_namescore
技术部大翔100
技术部白歌NULL

结果解读:先按 dept 升序排列,同一部门内再按 score 降序排列。当前表中所有员工都在技术部。

场景四:按表达式排序

当前数据状态:见上文 employees 表完整数据。

执行语句:

SELECT emp_name, dept FROM employees
ORDER BY dept = '技术部' DESC, emp_id ASC;

操作后结果:

emp_namedept
大翔技术部
白歌技术部

结果解读:ORDER BY 支持表达式和函数。这里 dept = '技术部' 返回 1(技术部)或 0(其他部门),按该表达式降序排序后,技术部的员工排在最前面;同值时再按 emp_id 升序排列。当前表中所有员工都在技术部。

场景五:按 SELECT 别名排序(合法)

当前数据状态:见上文 employees 表完整数据。

执行语句:

SELECT
    emp_name,
    IFNULL(score, 0) AS effective_score
FROM employees
ORDER BY effective_score DESC;

操作后结果:

emp_nameeffective_score
大翔100
白歌0

结果解读:虽然 WHERE 中不能用别名,但 ORDER BY 可以,因为 ORDER BY 在 SELECT 之后执行。此时别名 effective_score 已经生成,可以直接使用。当前表中只有大翔有有效绩效分。

场景六:指定字段位置排序(不推荐)

当前数据状态:见上文 employees 表完整数据。

执行语句:

SELECT emp_name, score FROM employees
ORDER BY 2 DESC;

操作后结果:

emp_namescore
大翔100
白歌NULL

结果解读:ORDER BY 2 表示按 SELECT 列表中的第 2 个列(即 score)降序排序。这种写法虽然合法,但可读性差且脆弱——一旦 SELECT 列顺序改变,排序逻辑就会出错。生产环境应使用列名。

场景七:NULL 的排序控制

MySQL 5.7 中,ORDER BY 对 NULL 的默认处理规则:

  • 升序(ASC):NULL 排在最前面
  • 降序(DESC):NULL 排在最后面

我们用 score 列验证(白歌的 score 为 NULL):

执行语句(升序,NULL 在前):

SELECT emp_name, score FROM employees ORDER BY score ASC;

操作后结果:

emp_namescore
白歌NULL
大翔100

结果解读:NULL 默认排在升序的最前面。

如需自定义 NULL 的位置,将 NULL 排在最后(升序时):

SELECT emp_name, score FROM employees
ORDER BY score IS NULL, score ASC;

操作后结果:

emp_namescore
大翔100
白歌NULL

结果解读:score IS NULL 返回 1(NULL)或 0(非 NULL),先按此排序,非 NULL(0)在前,NULL(1)在后,再按实际 score 值排序。这样 NULL 就被排到了最后。

常见误区

误区正解
"不指定 ORDER BY 结果也有顺序"没有 ORDER BY 的结果集顺序是未定义的,可能因索引、执行计划变化而不同。
ORDER BY 可以用在 WHERE 中ORDER BY 是结果集排序,不能用于 WHERE。
ORDER BY RAND() 随机排序很快ORDER BY RAND() 需要为每行生成随机数并全排序,大数据量时极慢。
"多列排序时第二个列没用"第二个列在第一个列值相同时才生效,是非常常用的功能。

面试考点

Q:ORDER BY 在 SQL 执行顺序中的位置?

ORDER BY 在 SELECT 之后、LIMIT 之前执行。因此它可以使用 SELECT 中定义的别名。

Q:大数据量排序慢怎么办?

  1. 确保 ORDER BY 的列上有索引;2. 如果只需要 Top N,配合 LIMIT 可减少排序数据量;3. 避免对大量数据进行无索引排序。

Q:如何实现"将 NULL 值排在最后"?

ORDER BY column IS NULL, column ASC。column IS NULL 返回 1(NULL)或 0(非 NULL),先按此排序,非 NULL 在前,再按实际值排序。

Q:ORDER BY 可以用函数吗?

可以,如 ORDER BY LENGTH(emp_name) DESC。但函数会阻止索引使用,大数据量时性能较差。

小结

  • ORDER BY 决定结果集的呈现顺序,不带则顺序未定义
  • 支持多列排序、表达式排序和别名引用
  • 避免使用字段位置序号排序,应使用列名
  • 大数据量排序应考虑索引优化
  • NULL 默认在升序时排最前,可用 column IS NULL 自定义位置

下一章引子:排序后的结果可能仍然很多,如果只想看前几条怎么办?

上一页
WHERE
下一页
LIMIT