MySQL ORDER BY 语句
从数据库中检索数据时,结果返回的顺序会极大地影响数据的可用性和分析效率。SQL 中的 ORDER BY 子句允许你根据一个或多个指定的列,对 SELECT 语句的结果集进行排序。该子句赋予了你控制数据呈现方式的能力,可以按升序或降序排列数据。
1. 使用 ORDER BY 进行基础排序
ORDER BY 最基础的用法是指定单个列进行排序。默认情况下,ORDER BY 会按升序对结果进行排序。为了明确定义排序顺序,你可以使用 ASC 关键字表示升序,或使用 DESC 关键字表示降序。
1.1 单列升序排序
当你按升序排序时,数值会从最小排列到最大,字母字符串从 A 排列到 Z,日期从最旧排列到最新。
示例 1:按姓名对客户进行排序
假设有一个名为 customers(客户)的表,包含 customer_id、first_name、last_name 和 city 等列。要检索所有客户并按他们的姓氏字母顺序排序:
SELECT
customer_id,
first_name,
last_name,
city
FROM
customers
ORDER BY
last_name ASC; -- 明确指定按 last_name(姓氏)进行升序排序这个查询会返回所有客户的详细信息,但行的排列方式是:姓氏以 'A' 开头的客户排在最前面,接着是 'B',以此类推。
示例 2:按价格对产品进行排序
想象一个包含 product_id、product_name 和 price 的 products(产品)表。要将产品从最便宜到最贵列出:
SELECT
product_id,
product_name,
price
FROM
products
ORDER BY
price; -- ASC 是默认值,因此可以省略输出结果会先显示价格较低的产品,然后逐步过渡到价格较高的商品。
1.2 单列降序排序
降序排列会反转排序规则:数值从最大排列到最小,字母字符串从 Z 排列到 A,日期从最新排列到最旧。
示例 3:按入职日期对员工进行排序
一个名为 employees(员工)的表可能包含 employee_id、first_name、last_name 和 hire_date。要首先查看最近入职的员工:
SELECT
employee_id,
first_name,
last_name,
hire_date
FROM
employees
ORDER BY
hire_date DESC; -- 按 hire_date(入职日期)进行降序排序这个查询会呈现员工列表,从最近雇佣的员工开始。
示例 4:按数量查找最畅销的商品
如果一个 sales(销售)表包含 item_id 和 quantity_sold(售出数量),要首先识别出销量最高的商品:
SELECT
item_id,
quantity_sold
FROM
sales
ORDER BY
quantity_sold DESC;结果将显示按 quantity_sold 从高到低排序的商品。
2. 多列排序
你可以在 ORDER BY 子句中指定多个列。提供多个列时,数据库会首先按照最左边指定的列进行排序。如果第一列中存在相同的值,数据库接着会使用第二列对这些行进行排序,依此类推。ORDER BY 子句中的每一列都可以有自己独立的 ASC 或 DESC 说明符。
示例 5:先按城市排序,再按姓氏排序
要将客户首先按他们所在的城市进行组织,然后对于同一城市内的客户,按他们的姓氏进行排序:
SELECT
customer_id,
first_name,
last_name,
city
FROM
customers
ORDER BY
city ASC, -- 首先按 city(城市)进行升序排序
last_name ASC; -- 然后对每个城市内的客户按 last_name(姓氏)进行升序排序这个查询会将所有来自 'New York' 的客户聚集在一起并按姓氏排序,接着是所有来自 'London' 的客户并按姓氏排序,以此类推。
示例 6:按订单状态(降序)然后按订单日期(降序)排序
考虑一个带有 order_id、customer_id、order_date 和 order_status 的 orders(订单)表。要先看到最近完成的订单,再看待处理的订单,并且在相同状态下优先看最新的订单:
SELECT
order_id,
customer_id,
order_date,
order_status
FROM
orders
ORDER BY
order_status DESC, -- 按状态排序(例如,'Completed' 排在 'Pending' 之前)
order_date DESC; -- 然后按 order_date 排序(最新的优先)如果 order_status 是一个字符串,在升序中 'Completed' 会排在 'Pending' 之后。在这里使用 DESC 会将 'Pending' 排在 'Completed' 之前(如果这是你想要的逻辑分组);或者如果使用的是状态代码(例如,1 代表待处理,2 代表已完成),DESC 就会将已完成 (2) 排在待处理 (1) 之前。
3. 按列位置排序
除了通过列名来引用列之外,你还可以通过它们在 SELECT 列表中的位置来引用它们。这种做法可读性较差,通常不推荐在生产环境查询中使用,因为对 SELECT 列表的更改(添加或删除列)可能会导致查询出错。不过,这是一种有效的语法。
示例 7:按列位置排序
使用示例 3 中的 employees 表:
SELECT
employee_id, -- 第 1 列
first_name, -- 第 2 列
last_name, -- 第 3 列
hire_date -- 第 4 列
FROM
employees
ORDER BY
4 DESC; -- 按 SELECT 列表中的第 4 列(即 hire_date)进行降序排序这个查询实现了与示例 3 相同的结果,但使用了列位置 4 而不是 hire_date。
4. 结合 WHERE 子句排序
当 SELECT 语句中同时使用 WHERE 和 ORDER BY 时,ORDER BY 子句通常放置在 WHERE 子句之后。数据库会先使用 WHERE 子句过滤行,然后再使用 ORDER BY 对过滤后的结果集进行排序。
示例 8:过滤并排序客户
仅检索来自 'New York' 的客户,并按他们的姓氏排序:
SELECT
customer_id,
first_name,
last_name,
city
FROM
customers
WHERE
city = 'New York' -- 过滤出位于纽约的客户
ORDER BY
last_name ASC; -- 然后将过滤后的结果按姓氏排序此查询首先选择 city 为 'New York' 的所有客户,然后再将仅有的这些特定客户按姓氏的字母顺序排列。这演示了 WHERE 子句如何在 ORDER BY 组织数据之前先缩小数据范围。
5. NULL 值与排序
当对包含 NULL(空)值的列进行排序时,不同数据库系统处理 NULL 的行为可能会有所不同。在 MySQL 中,排序时 NULL 值被视为最低可能的值。因此,在 ASC(升序)排序中它们会出现在最前面,而在 DESC(降序)排序中它们会出现在最后面。
示例 9:包含 NULL 值的排序
考虑一个 employees 表,其中包含一个 manager_id 列,对于最高层级的员工,该列可能为 NULL。
SELECT
employee_id,
first_name,
manager_id
FROM
employees
ORDER BY
manager_id ASC; -- NULL 值将首先出现在升序排列中,manager_id 为 NULL 的员工(通常是高层管理人员)将被列在最前面。
SELECT
employee_id,
first_name,
manager_id
FROM
employees
ORDER BY
manager_id DESC; -- NULL 值将最后出现在降序排列中,manager_id 为 NULL 的员工将被列在最后面。
在解释排序结果时,这种行为非常重要,特别是当处理 NULL 代表“未知”或“不适用”的列时。