學習重點
使用
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
子句中不要使用列編號。
請參閱
(完)