本章将介绍如何使用 SELECT 语句的 ORDER BY 子句,根据需要对查询出的数据进行排序。
正如前一面所述,下面的 SQL 语句将返回 user 数据库表的 name 列的数据,仔细查看其输出,并没有特定的顺序。如下:
select name from user
输出如下:
name| ----+ 张三 | 李四 | 王五 | 赵六 | 孙七 | 周八 | 吴九 | 郑十 | 钱十一 | 孙十二 | 10 row(s) fetched.
其实,查询数据不会随机显示,默认按表中存储顺序展示(一般是初始插入顺序)。但数据更新或删除后,DBMS 重用存储空间可能打乱这个顺序,所以未明确指定排序时,不能也不应依赖默认顺序。按数据库设计理论,未规定排序的查询结果,其顺序无意义。
在 SQL 中,一个 SELECT 语句由多个子句构成,有些子句是必需的,而有的子句是可选。一个子句通常由一个关键字加上所提供的数据组成。例如:
SELECT 子句:select name
FROM 子句:from user
为了明确地告诉 SELECT 查询出的数据该如何排序?可使用 ORDER BY 子句。ORDER BY 子句取一个或多个列的名字,根据这些列对输出进行排序。例如:
select user_id, name from user order by name
上述 SQL 条语句除了以 name 列按字母顺序排序数据的 ORDER BY 子句外,与前面的语句相同。结果如下:
user_id|name| -------+----+ 7|吴九 | 6|周八 | 5|孙七 | 10|孙十二 | 1|张三 | 2|李四 | 3|王五 | 4|赵六 | 8|郑十 | 9|钱十一 | 10 row(s) fetched.
注意,在指定一条 ORDER BY 子句时,应保证它是 SELECT 语句中最后一条子句。并且,作为 ORDER BY 子句排序的列并非一定要出现在 SELECT 子句列表中。例如:
select user_id, name from user order by age
上面 SQL 语句将按照 age 对查询数据排序,age 并没有在 SELECT 子句中,这是合法的。
实际场景中,常需按多个列对数据排序。例如显示用户列表时,可以要先按性别排序,再在同一性别下按年龄排序。
按多列排序的操作很简单,只需在 ORDER BY 子句后依次指定列名,列名之间用逗号分隔。例如:
select * from user order by gender, age
输出如下:
user_id|name|gender|age|phone |email |address |create_time |update_time | -------+----+------+---+-----------+---------------------+---------------+-------------------+-------------------+ 7|吴九 | | 32|13800138006|wujiu@example.com |重庆市渝中区解放碑路18号 |2025-01-06 19:15:00|2025-12-24 14:44:13| 9|钱十一 |男 | 24|13800138008|qianshiyi@example.com|西安市雁塔区雁塔路15号 |2025-01-22 15:08:00|2025-12-24 14:44:13| 1|张三 |男 | 25|13800138000|zhangsan@example.com |北京市朝阳区建国路88号 |2025-01-24 02:41:00|2025-12-24 14:44:13| 3|王五 |男 | 28|13800138002|wangwu@example.com |广州市天河区天河路385号 |2025-01-19 15:49:00|2025-12-24 14:44:13| 5|孙七 |男 | 35|13800138004| |杭州市西湖区西湖路58号 |2025-01-27 12:17:00|2025-12-24 14:44:13| 4|赵六 |女 | 22|13800138003|zhaoliu@example.com |深圳市南山区科技园10号 |2025-01-11 11:56:00|2025-12-24 14:44:13| 6|周八 |女 | 27|13800138005|zhouba@example.com |成都市武侯区武侯祠大街231号|2025-01-12 01:37:00|2025-12-24 14:44:13| 8|郑十 |女 | 29|13800138007|zhengshi@example.com |武汉市武昌区中南路99号 |2025-01-26 19:22:00|2025-12-24 14:44:13| 2|李四 |女 | 30|13800138001|lisi@example.com |上海市浦东新区张江路100号 |2025-01-18 14:22:00|2025-12-24 14:44:13| 10|孙十二 |女 | 31|13800138009| |南京市玄武区玄武湖路78号 |2025-01-01 17:34:00|2025-12-24 14:44:13| 10 row(s) fetched.
上述结果中,先按性别(gender)排序,再按年龄(age)排序。
除了能用列名指出排序顺序外,ORDER BY 还支持按相对列位置进行排序。例如:
select * from user order by 3, 4
输出如下:
user_id|name|gender|age|phone |email |address |create_time |update_time | -------+----+------+---+-----------+---------------------+---------------+-------------------+-------------------+ 7|吴九 | | 32|13800138006|wujiu@example.com |重庆市渝中区解放碑路18号 |2025-01-06 19:15:00|2025-12-24 14:44:13| 9|钱十一 |男 | 24|13800138008|qianshiyi@example.com|西安市雁塔区雁塔路15号 |2025-01-22 15:08:00|2025-12-24 14:44:13| 1|张三 |男 | 25|13800138000|zhangsan@example.com |北京市朝阳区建国路88号 |2025-01-24 02:41:00|2025-12-24 14:44:13| 3|王五 |男 | 28|13800138002|wangwu@example.com |广州市天河区天河路385号 |2025-01-19 15:49:00|2025-12-24 14:44:13| 5|孙七 |男 | 35|13800138004| |杭州市西湖区西湖路58号 |2025-01-27 12:17:00|2025-12-24 14:44:13| 4|赵六 |女 | 22|13800138003|zhaoliu@example.com |深圳市南山区科技园10号 |2025-01-11 11:56:00|2025-12-24 14:44:13| 6|周八 |女 | 27|13800138005|zhouba@example.com |成都市武侯区武侯祠大街231号|2025-01-12 01:37:00|2025-12-24 14:44:13| 8|郑十 |女 | 29|13800138007|zhengshi@example.com |武汉市武昌区中南路99号 |2025-01-26 19:22:00|2025-12-24 14:44:13| 2|李四 |女 | 30|13800138001|lisi@example.com |上海市浦东新区张江路100号 |2025-01-18 14:22:00|2025-12-24 14:44:13| 10|孙十二 |女 | 31|13800138009| |南京市玄武区玄武湖路78号 |2025-01-01 17:34:00|2025-12-24 14:44:13| 10 row(s) fetched.
正如所见,这里的输出与上面的按多个列排序查询相同。不同之处在于 ORDER BY 子句不是使用列名,则是使用位置信息。
SQL 中对查询结果的排序并非只能采用默认的 ASC(ASC 是 ASCENDING 的缩写)升序方式(即从 A 到 Z、从小到大的排序逻辑)。
注意,升序排序是 ORDER BY 子句的默认行为,无需额外指定关键字,例如:
select * from user order by gender, age; -- 等价 select * from user order by gender asc, age asc;
如果需要按照相反的逻辑 —— 降序(从 Z 到 A、从大到小)排序,则必须在 ORDER BY 子句中为目标排序列明确指定 DESC 关键字(DESC 是 DESCENDING 的缩写,意为 “降序”)。
ASC 升序,从小到大,从 A 到 Z
DESC 降序,从大到小,从 Z 到 A
示例:性别按照升序,年龄按照降序排序
select * from user order by gender ASC, age DESC
输出如下:
user_id|name|gender|age|phone |email |address |create_time |update_time | -------+----+------+---+-----------+---------------------+---------------+-------------------+-------------------+ 7|吴九 | | 32|13800138006|wujiu@example.com |重庆市渝中区解放碑路18号 |2025-01-06 19:15:00|2025-12-24 14:44:13| 5|孙七 |男 | 35|13800138004| |杭州市西湖区西湖路58号 |2025-01-27 12:17:00|2025-12-24 14:44:13| 3|王五 |男 | 28|13800138002|wangwu@example.com |广州市天河区天河路385号 |2025-01-19 15:49:00|2025-12-24 14:44:13| 1|张三 |男 | 25|13800138000|zhangsan@example.com |北京市朝阳区建国路88号 |2025-01-24 02:41:00|2025-12-24 14:44:13| 9|钱十一 |男 | 24|13800138008|qianshiyi@example.com|西安市雁塔区雁塔路15号 |2025-01-22 15:08:00|2025-12-24 14:44:13| 10|孙十二 |女 | 31|13800138009| |南京市玄武区玄武湖路78号 |2025-01-01 17:34:00|2025-12-24 14:44:13| 2|李四 |女 | 30|13800138001|lisi@example.com |上海市浦东新区张江路100号 |2025-01-18 14:22:00|2025-12-24 14:44:13| 8|郑十 |女 | 29|13800138007|zhengshi@example.com |武汉市武昌区中南路99号 |2025-01-26 19:22:00|2025-12-24 14:44:13| 6|周八 |女 | 27|13800138005|zhouba@example.com |成都市武侯区武侯祠大街231号|2025-01-12 01:37:00|2025-12-24 14:44:13| 4|赵六 |女 | 22|13800138003|zhaoliu@example.com |深圳市南山区科技园10号 |2025-01-11 11:56:00|2025-12-24 14:44:13| 10 row(s) fetched.
注意:DESC 关键字仅作用于紧跟其后的列名,如果要对多个列分别指定排序方向,需为每个列单独标注。
在对文本类型的数据执行排序操作时,一个核心且实际的问题是:字符的大小写是否会影响排序结果?比如字母 “A” 与 “a” 是否被视为同一字符?小写的 “a” 会排在大写的 “B” 之前,还是排在大写的 “Z” 之后?这些并非纯理论问题,其答案完全取决于数据库的底层配置(包括字符集、排序规则(Collation)等),直接影响排序结果的准确性。
在绝大多数数据库管理系统(DBMS)中,默认采用 “字典序(dictionary sort order)” 规则 —— 即不区分字母的大小写,将 “A” 和 “a” 视为等同,排序时会忽略大小写差异(例如 “Apple” 和 “apple” 会被归为同一排序层级,“banana” 会排在 “Zoo” 之前)。这一默认行为适配了大多数通用业务场景,比如检索用户姓名、产品名称时,无需区分大小写的排序需求。
但这种默认规则并非不可调整:许多主流 DBMS(如 MySQL、PostgreSQL、SQL Server 等)允许数据库管理员(DBA)根据业务需求修改排序的大小写敏感规则。尤其是当数据库中包含大量外语字符(如带重音的西语字符、多字节的中文 / 日文字符),或业务场景明确要求区分大小写(例如系统用户名、密码相关的排序 / 检索)时,调整排序规则就成为必要操作 —— 比如将排序规则改为 “大小写敏感(Case-Sensitive)”,此时 “A” 会被判定为与 “a” 不同,且在排序中 “A” 会优先于 “a”。
注意:如果业务场景要求改变默认的大小写排序逻辑,仅通过ORDER BY子句是无法实现的。ORDER BY仅能指定排序的列和升降序方向,无法修改数据库底层的排序规则。想要调整大小写敏感策略或适配特殊字符的排序逻辑,必须由具备权限的数据库管理员操作 ——DBA 会通过修改数据库 / 表的排序规则来完成配置,普通开发人员无法通过简单的 SQL 语句自行变更。