SQL对查询结果进行排序(ORDERBY)

目录
- 一、ORDER BY 子句
- 二、指定升序或降序
- 三、指定多个排序键
- 四、NULL 的顺序
- 五、在排序键中使用显示用的别名
- 六、ORDER BY 子句中可以使用的列
- 七、不要使用列编号
- 请参阅
学习重点
使用
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子句中不要使用列编号。
请参阅
- 对表进行聚合查询
- 对表进行分组
- 为聚合结果指定条件
- 对查询结果进行排序
(完)
也是因为这一原因,
HAVING子句也不能使用别名。 ↩︎1992 年制定的 SQL 标准。 ↩︎
以上是 SQL对查询结果进行排序(ORDERBY) 的全部内容, 来源链接: utcz.com/z/536088.html

