學習重點
使用
ORDER BY子句對查詢結果進行排序。在
ORDER BY子句中列名的后面使用關鍵字ASC可以進行升序排序,使用DESC關鍵字可以進行降序排序。
ORDER BY子句中可以指定多個排序鍵。排序健中包含
NULL時,會在開頭或末尾進行匯總。
ORDER BY子句中可以使用SELECT子句中定義的列的別名。
ORDER BY子句中可以使用SELECT子句中未出現的列或者聚合函數。
ORDER BY子句中不能使用列的編號。
一、ORDER BY 子句
截至目前,我們使用了各種各樣的條件對表中的數據進行查詢。本節讓我們再來回顧一下簡單的 SELECT 語句(代碼清單 27)。
代碼清單 27 顯示商品編號、商品名稱、銷售單價和進貨單價的 SELECT 語句
SELECT product_id, product_name, sale_price, purchase_price
FROM Product;
執行結果
product_id | product_name | sale_price | purchase_price
------------+---------------+--------------+----------------
0001 | T恤衫 | 1000 | 500
0002 | 打孔器 | 500 | 320
0003 | 運動T恤 | 4000 | 2800
0004 | 菜刀 | 3000 | 2800
0005 | 高壓鍋 | 6800 | 5000
0006 | 叉子 | 500 |
0007 | 擦菜板 | 880 | 790
0008 | 圓珠筆 | 100 |
對於上述結果,在此無需特別說明,本節要為大家介紹的不是查詢結果,而是查詢結果的排列順序。
那么,結果中的 8 行記錄到底是按照什么順序排列的呢?乍一看,貌似是按照商品編號從小到大的順序(升序)排列的。其實,排列順序是隨機的,這只是個偶然。因此,再次執行同一條 SELECT 語句時,順序可能大為不同。
KEYWORD
- 升序
通常,從表中抽取數據時,如果沒有特別指定順序,最終排列順序便無從得知。即使是同一條 SELECT 語句,每次執行時排列順序很可能發生改變。
但是不進行排序,很可能出現結果混亂的情況。這時,便需要通過在 SELECT 語句末尾添加 ORDER BY 子句來明確指定排列順序。
KEYWORD
ORDER BY子句
ORDER BY 子句的語法如下所示。
語法 4 ORDER BY 子句
SELECT <列名1>, <列名2>, <列名3>, ……
FROM <表名>
ORDER BY <排序基准列1>, <排序基准列2>, ……
例如,按照銷售單價由低到高,也就是升序排列時,請參見代碼清單 28。
代碼清單 28 按照銷售單價由低到高(升序)進行排列
SELECT product_id, product_name, sale_price, purchase_price
FROM Product
ORDER BY sale_price;
執行結果

不論何種情況,ORDER BY 子句都需要寫在 SELECT 語句的末尾。這是因為對數據行進行排序的操作必須在結果即將返回時執行。ORDER BY 子句中書寫的列名稱為排序鍵。該子句與其他子句的順序關系如下所示。
KEYWORD
- 排序鍵
▶ 子句的書寫順序
SELECT子句 → 2.FROM子句 → 3.WHERE子句 → 4.GROUP BY子句 → 5.HAVING子句 → 6.ORDER BY子句
法則 15
ORDER BY子句通常寫在 SELECT 語句的末尾。
不想指定數據行的排列順序時,SELECT 語句中不寫 ORDER BY 子句也沒關系。
二、指定升序或降序
與上述示例相反,想要按照銷售單價由高到低,也就是降序排列時,可以參見代碼清單 29,在列名后面使用 DESC 關鍵字。
KEYWORD
降序
DESC關鍵字
代碼清單 29 按照銷售單價由高到低(降序)進行排列
SELECT product_id, product_name, sale_price, purchase_price
FROM Product
ORDER BY sale_price DESC;
執行結果
product_id | product_name | sale_ price | purchase_ price
------------+--------------+-------------+----------------
0005 | 高壓鍋 | 6800 | 5000
0003 | 運動T恤 | 4000 | 2800
0004 | 菜刀 | 3000 | 2800
0001 | T恤衫 | 1000 | 500
0007 | 擦菜板 | 880 | 790
0002 | 打孔器 | 500 | 320
0006 | 叉子 | 500 |
0008 | 圓珠筆 | 100 |
如上所示,這次銷售單價最高(6800 日元)的高壓鍋排在了第一位。其實,使用升序進行排列時,正式的書寫方式應該是使用關鍵字 ASC,但是省略該關鍵字時會默認使用升序進行排序。這可能是因為實際應用中按照升序排序的情況更多吧。ASC 和 DESC 是 ascendent(上升的)和 descendent(下降的)這兩個單詞的縮寫。
KEYWORD
ASC關鍵字
法則 16
未指定
ORDER BY子句中排列順序時會默認使用升序進行排列。
由於 ASC 和 DESC 這兩個關鍵字是以列為單位指定的,因此可以同時指定一個列為升序,指定其他列為降序。
三、指定多個排序鍵
本節開頭曾提到過對銷售單價進行升序排列的 SELECT 語句(代碼清單 28)的執行結果,我們再來回顧一下。可以發現銷售單價為 500 日元的商品有 2 件。相同價格的商品的順序並沒有特別指定,或者可以說是隨機排列的。
如果想要對該順序的商品進行更細致的排序的話,就需要再添加一個排序鍵。在此,我們以添加商品編號的升序為例,請參見代碼清單 30。
代碼清單 30 按照銷售單價和商品編號的升序進行排序
SELECT product_id, product_name, sale_price, purchase_price
FROM Product
ORDER BY sale_price, product_id;
執行結果

這樣一來,就可以在 ORDER BY 子句中同時指定多個排序鍵了。規則是優先使用左側的鍵,如果該列存在相同值的話,再接着參考右側的鍵。當然,也可以同時使用 3 個以上的排序鍵。
四、NULL 的順序
在此前的示例中,我們已經使用過銷售單價(sale_price 列)作為排序鍵了,這次讓我們嘗試使用進貨單價(purchase_price 列)作為排序鍵吧。此時,問題來了,圓珠筆和叉子對應的值是 NULL,究竟 NULL 會按照什么順序進行排列呢? NULL 是大於 100 還是小於 100 呢?或者說 5000 和 NULL 哪個更大呢?
請大家回憶一下我們在 算術運算符和比較運算符 中學過的內容。沒錯,不能對 NULL 使用比較運算符,也就是說,不能對 NULL 和數字進行排序,也不能與字符串和日期比較大小。因此,使用含有 NULL 的列作為排序鍵時, NULL 會在結果的開頭或末尾匯總顯示(代碼清單 31)。
代碼清單 31 按照進貨單價的升序進行排列
SELECT product_id, product_name, sale_price, purchase_price
FROM Product
ORDER BY purchase_price;
執行結果

究竟是在開頭顯示還是在末尾顯示,並沒有特殊規定。某些 DBMS 中可以指定 NULL 在開頭或末尾顯示,希望大家對自己使用的 DBMS 的功能研究一下。
法則 17
排序鍵中包含
NULL時,會在開頭或末尾進行匯總。
五、在排序鍵中使用顯示用的別名
在 對表進行分組 中“常見錯誤 ②”中曾介紹過,在 GROUP BY 子句中不能使用 SELECT 子句中定義的別名,但是在 ORDER BY 子句中卻是允許使用別名的。因此,代碼清單 32 中的 SELECT 語句並不會出錯,可正確執行。
代碼清單 32 ORDER BY 子句中可以使用列的別名
SELECT product_id AS id, product_name, sale_price AS sp, purchase_price
FROM Product
ORDER BY sp, id;
上述 SELECT 語句與之前按照“銷售單價和商品編號的升序進行排列”的 SELECT 語句(代碼清單 31)意思完全相同。
執行結果
id | product_name | sp | purchase_price
------+---------------+-------+---------------
0008 | 圓珠筆 | 100 |
0002 | 打孔器 | 500 | 320
0006 | 叉子 | 500 |
0007 | 擦菜板 | 880 | 790
0001 | T恤衫 | 1000 | 500
0004 | 菜刀 | 3000 | 2800
0003 | 運動T恤 | 4000 | 2800
0005 | 高壓鍋 | 6800 | 5000
不能在 GROUP BY 子句中使用的別名,為什么可以在 ORDER BY 子句中使用呢?這是因為 SQL 語句在 DBMS 內部的執行順序被掩蓋起來了。SELECT 語句按照子句為單位的執行順序如下所示。
▶ 使用 HAVING 子句時 SELECT 語句的順序
FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY
這只是一個粗略的總結,雖然具體的執行順序根據 DBMS 的不同而不同,但是大家有這樣一個大致的印象就可以了。一定要記住 SELECT 子句的執行順序在 GROUP BY 子句之后,ORDER BY 子句之前。因此,在執行 GROUP BY 子句時,SELECT 語句中定義的別名無法被識別 [1]。對於在 SELECT 子句之后執行的 ORDER BY 子句來說,就沒有這樣的問題了。
法則 18
在
ORDER BY子句中可以使用SELECT子句中定義的別名。
六、ORDER BY 子句中可以使用的列
ORDER BY 子句中也可以使用存在於表中、但並不包含在 SELECT 子句之中的列(代碼清單 33)。
代碼清單 33 SELECT 子句中未包含的列也可以在 ORDER BY 子句中使用
SELECT product_name, sale_price, purchase_price
FROM Product
ORDER BY product_id;
執行結果
product_name | sale_price | purchase_price
---------------+-------------+----------------
T恤衫 | 1000 | 500
打孔器 | 500 | 320
運動T恤 | 4000 | 2800
菜刀 | 3000 | 2800
高壓鍋 | 6800 | 5000
叉子 | 500 |
擦菜板 | 880 | 790
圓珠筆 | 100 |
除此之外,還可以使用聚合函數(代碼清單 34)。
代碼清單 34 ORDER BY 子句中也可以使用聚合函數

執行結果
product_type | count
---------------+------
衣服 | 2
辦公用品 | 2
廚房用具 | 4
法則 19
在
ORDER BY子句中可以使用SELECT子句中未使用的列和聚合函數。
七、不要使用列編號
在 ORDER BY 子句中,還可以使用在 SELECT 子句中出現的列所對應的編號,是不是沒想到?列編號是指 SELECT 子句中的列按照從左到右的順序進行排列時所對應的編號(1, 2, 3,…)。因此,代碼清單 35 中的兩條 SELECT 語句的含義是相同的。
KEYWORD
- 列編號
代碼清單 35 ORDER BY 子句中可以使用列的編號
-- 通過列名指定
SELECT product_id, product_name, sale_price, purchase_price
FROM Product
ORDER BY sale_price DESC, product_id;
-- 通過列編號指定
SELECT product_id, product_name, sale_price, purchase_price
FROM Product
ORDER BY 3 DESC, 1;
上述第 2 條 SELECT 語句中的 ORDER BY 子句所代表的含義,就是“按照 SELECT 子句中第 3 列的降序和第 1 列的升序進行排列”,這和第 1 條 SELECT 語句的含義完全相同。
執行結果
product_id | product_name | sale_price | purchase_price
-----------+---------------+-------------+----------------
0005 | 高壓鍋 | 6800 | 5000
0003 | 運動T恤 | 4000 | 2800
0004 | 菜刀 | 3000 | 2800
0001 | T恤衫 | 1000 | 500
0007 | 擦菜板 | 880 | 790
0002 | 打孔器 | 500 | 320
0006 | 叉子 | 500 |
0008 | 圓珠筆 | 100 |
雖然列編號使用起來非常方便,但我們並不推薦使用,原因有以下兩點。
第一,代碼閱讀起來比較難。使用列編號時,如果只看 ORDER BY 子句是無法知道當前是按照哪一列進行排序的,只能去 SELECT 子句的列表中按照列編號進行確認。上述示例中 SELECT 子句的列數比較少,因此可能並沒有什么明顯的感覺。但是在實際應用中往往會出現列數很多的情況,而且 SELECT 子句和 ORDER BY 子句之間,還可能包含很復雜的 WHERE 子句和 HAVING 子句,直接人工確認實在太麻煩了。
第二,這也是最根本的問題,實際上,在 SQL-92 [2] 中已經明確指出該排序功能將來會被刪除。因此,雖然現在使用起來沒有問題,但是將來隨着 DBMS 的版本升級,可能原本能夠正常執行的 SQL 突然就會出錯。不光是這種單獨使用的 SQL 語句,對於那些在系統中混合使用的 SQL 來說,更要極力避免。
法則 20
在
ORDER BY子句中不要使用列編號。
請參閱
(完)
