SQL ORDER BY:对查询结果排序
第 2.6 课 · 阅读时间:约 6 分钟 · 练习题 ↓
SQL ORDER BY 子句按一个或多个列或表达式对查询结果的行进行排序。在本课中,你将学习升序和降序排序、按多列排序、按表达式和别名排序,以及 NULL 值的排序方式。
表本身没有内置的行顺序。没有 ORDER BY 时,数据库会按照对它最方便的顺序返回行,而且每次运行的顺序都可能不同。只要顺序很重要-例如报表、排行榜或按时间排列的日志-就必须明确指定。
ORDER BY 子句
ORDER BY 写在 SELECT 语句的末尾,列出排序键。
基本语法
SELECT column1, column2, ...
FROM table_name
ORDER BY column1 [ASC | DESC], column2 [ASC | DESC], ...;
ASC按升序排序:从小到大、从 A 到 Z、从早到晚。这是默认顺序。DESC按降序排序。
按单列排序
SELECT first_name, last_name
FROM actor
ORDER BY last_name;
结果:所有演员按姓氏的字母顺序排列。
要反转顺序,请添加 DESC:
SELECT title, length
FROM film
ORDER BY length DESC;
结果:电影从最长到最短排列。
按多列排序
当第一个排序键的值相同时,数据库使用第二个排序键对这些行排序,然后是第三个,依此类推:
SELECT first_name, last_name
FROM actor
ORDER BY last_name, first_name;
结果:演员按姓氏排序;姓氏相同的演员再按名字排序。
每一列都有自己的排序方向。ASC 或 DESC 只作用于它前面的那一列:
SELECT title, rating, length
FROM film
ORDER BY rating, length DESC;
结果:电影按分级分组;在每个分级内,最长的电影排在最前面。
按表达式排序
你不仅可以按存储的列排序,也可以按计算出的值排序。表达式会针对每一行计算,然后按结果对行排序:
SELECT title, rental_rate, rental_duration
FROM film
ORDER BY rental_rate * rental_duration DESC;
结果:电影按整个租期的租赁费用排序,最贵的排在最前面。
比较运算也可以作为排序键,这便于把某些行放到最上面:
SELECT title, rating
FROM film
ORDER BY rating = 'G' DESC, title;
结果:分级为 G 的电影排在最上面,然后是其他所有电影;每组内按片名排序。
在 MySQL 和 MariaDB 中,比较运算返回 1 或 0,因此 DESC 会把匹配的行排在前面。并非所有数据库都能按比较运算排序;可移植的写法使用 CASE,你将在第 3.5 课中学习。
按别名和列位置排序
ORDER BY 在 SELECT 之后处理,因此可以使用在 SELECT 中定义的列别名:
SELECT title, rental_rate * rental_duration AS full_rental_cost
FROM film
ORDER BY full_rental_cost DESC;
也可以按列在 SELECT 列表中的位置排序:
SELECT first_name, last_name
FROM actor
ORDER BY 2, 1;
结果:演员先按第二列(last_name)排序,再按第一列(first_name)排序。
按位置排序在临时查询中很方便,但当有人修改列列表时,它会悄无声息地失效。在需要保存的查询中,请使用列名或别名。
排序与 NULL 值
NULL 表示“没有值”,因此数据库必须决定把这些行放在哪里。在 MySQL、MariaDB 和 SQL Server 中,升序时 NULL 值排在最前面,降序时排在最后。PostgreSQL 和 Oracle 则相反。
SELECT rental_id, rental_date, return_date
FROM rental
ORDER BY return_date
LIMIT 10;
结果:在 MySQL 中,尚未归还的租赁(return_date 为 NULL)排在最前面。
要点:
- 没有
ORDER BY,结果中行的顺序就没有保证。 ASC(默认)按升序排序,DESC按降序排序。- 有多个排序键时,每个后续键对前一个键相同的行进行排序。
ASC和DESC分别作用于每一列。- 可以按表达式、别名和列位置排序;列名和别名比位置更可靠。
NULL值出现的位置取决于数据库。
常见问题
SQL 默认的排序顺序是什么?
升序(ASC)。ORDER BY last_name 和 ORDER BY last_name ASC 返回相同的结果。
如何按多列以不同方向排序?
在每一列后面写出方向:ORDER BY rating ASC, length DESC。排序方向只作用于它前面的列。
可以在 ORDER BY 中使用列别名吗?
可以。ORDER BY 在 SELECT 之后处理,所以 SELECT 列表中定义的别名在这里可用。这一点与 WHERE 不同,WHERE 中不能使用别名。