SQL 查询数据:对查询数据排序(ORDER BY)

本章将介绍如何使用 SELECT 语句的 ORDER BY 子句,根据需要对查询出的数据进行排序。

数据排序

正如前一面所述,下面的 SQL 语句将返回 user 数据库表的 name 列的数据,仔细查看其输出,并没有特定的顺序。如下:

select name from user

输出如下:

name|
----+
张三  |
李四  |
王五  |
赵六  |
孙七  |
周八  |
吴九  |
郑十  |
钱十一 |
孙十二 |

10 row(s) fetched.

其实,查询数据不会随机显示,默认按表中存储顺序展示(一般是初始插入顺序)。但数据更新或删除后,DBMS 重用存储空间可能打乱这个顺序,所以未明确指定排序时,不能也不应依赖默认顺序。按数据库设计理论,未规定排序的查询结果,其顺序无意义。

ORDER BY 子句

在 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 语句自行变更。

  

说说我的看法
全部评论(
没有评论
关于
本网站专注于 Java、数据库(MySQL、Oracle)、Linux、软件架构及大数据等多领域技术知识分享。涵盖丰富的原创与精选技术文章,助力技术传播与交流。无论是技术新手渴望入门,还是资深开发者寻求进阶,这里都能为您提供深度见解与实用经验,让复杂编码变得轻松易懂,携手共赴技术提升新高度。如有侵权,请来信告知:hxstrive@outlook.com
其他应用
公众号