排序检索数据

本章将讲授如何使用SELECT语句的ORDER BY子句,根据需要排序检索数据。

排序数据

下面SQL语句返回数据库的单列,但输出没有特定的顺序:

mysql> SELECT prod_name
    -> FROM products;
+----------------+
| prod_name      |
+----------------+
| .5 ton anvil   |
| 1 ton anvil    |
| 2 ton anvil    |
| Detonator      |
| Bird seed      |
| Carrots        |
| Fuses          |
| JetPack 1000   |
| JetPack 2000   |
| Oil can        |
| Safe           |
| Sling          |
| TNT (1 stick)  |
| TNT (5 sticks) |
+----------------+
14 rows in set (0.02 sec)

检索出的数据并不是纯粹的随机顺序。如果不排序,数据一般以底层表中出现的顺序显示(数据添加到表的顺序)。但底层表数据顺序会被数据更新或删除影响。所以如果不明确规定排序顺序,则不应该假定检索出的数据的顺序有意义。

子句(clause) SQL语句由子句构成,有些子句必须,而有些子句可选。一个子句通常由一个关键字和所提供的数据组成。

为了明确地排序用SELECT语句检索出的数据,可以使用ORDER BY子句。
ORDER BY子句取一个或多个列的名字,据此对输出进行排序。

mysql> SELECT prod_name
    -> FROM products
    -> ORDER BY prod_name;
+----------------+
| prod_name      |
+----------------+
| .5 ton anvil   |
| 1 ton anvil    |
| 2 ton anvil    |
| Bird seed      |
| Carrots        |
| Detonator      |
| Fuses          |
| JetPack 1000   |
| JetPack 2000   |
| Oil can        |
| Safe           |
| Sling          |
| TNT (1 stick)  |
| TNT (5 sticks) |
+----------------+
14 rows in set (0.01 sec)

这条语句使用ORDER BY语句指示MySQL对prod_name列以字母顺序排序数据,其他与上个例子相同。

  • 通过非选择列进行排序 通常,ORDER BY子句中使用的列是结果显示列。但也可以不使用结果列中的列进行排序。

按多个列排序

我们排序经常需要按不止一个列进行数据排序。例如按名字排序需要先按姓排序后按名排序。

为了按多个列排序,只需指定列名,列名间用逗号分开(同选择多个行那样)。

下面代码检索三个列,并按两个列对结果排序(先按价格排序,后按名称排序)。

mysql> SELECT prod_id, prod_price, prod_name
    -> FROM products
    -> ORDER BY prod_price, prod_name;
+---------+------------+----------------+
| prod_id | prod_price | prod_name      |
+---------+------------+----------------+
| FC      |       2.50 | Carrots        |
| TNT1    |       2.50 | TNT (1 stick)  |
| FU1     |       3.42 | Fuses          |
| SLING   |       4.49 | Sling          |
| ANV01   |       5.99 | .5 ton anvil   |
| OL1     |       8.99 | Oil can        |
| ANV02   |       9.99 | 1 ton anvil    |
| FB      |      10.00 | Bird seed      |
| TNT2    |      10.00 | TNT (5 sticks) |
| DTNTR   |      13.00 | Detonator      |
| ANV03   |      14.99 | 2 ton anvil    |
| JP1000  |      35.00 | JetPack 1000   |
| SAFE    |      50.00 | Safe           |
| JP2000  |      55.00 | JetPack 2000   |
+---------+------------+----------------+
14 rows in set (0.00 sec)

注意:按多个列排序时,排序完全按所规定的顺序进行。类似于按顺序成组排序,每次排序都是在组内排序,例如若prod_price没有重复的值(即每行自成一组),那再按prod_name排序将对结果无影响(每组只有一条记录)。

指定排序方向

数据排序不限于升序排序(从A到Z)。这只是默认排序顺序,还可以通过DESC关键词进行降序排序。

按价格以降序排序产品(最贵的在前面):

mysql> SELECT prod_id, prod_price, prod_name
    -> FROM products
    -> ORDER BY prod_price DESC;
+---------+------------+----------------+
| prod_id | prod_price | prod_name      |
+---------+------------+----------------+
| JP2000  |      55.00 | JetPack 2000   |
| SAFE    |      50.00 | Safe           |
| JP1000  |      35.00 | JetPack 1000   |
| ANV03   |      14.99 | 2 ton anvil    |
| DTNTR   |      13.00 | Detonator      |
| FB      |      10.00 | Bird seed      |
| TNT2    |      10.00 | TNT (5 sticks) |
| ANV02   |       9.99 | 1 ton anvil    |
| OL1     |       8.99 | Oil can        |
| ANV01   |       5.99 | .5 ton anvil   |
| SLING   |       4.49 | Sling          |
| FU1     |       3.42 | Fuses          |
| FC      |       2.50 | Carrots        |
| TNT1    |       2.50 | TNT (1 stick)  |
+---------+------------+----------------+
14 rows in set (0.00 sec)

对多个列排序时,只需对需要降序的列后添加DESC关键字:

mysql> SELECT prod_id, prod_price, prod_name
    -> FROM products
    -> ORDER BY prod_price DESC, prod_name;
+---------+------------+----------------+
| prod_id | prod_price | prod_name      |
+---------+------------+----------------+
| JP2000  |      55.00 | JetPack 2000   |
| SAFE    |      50.00 | Safe           |
| JP1000  |      35.00 | JetPack 1000   |
| ANV03   |      14.99 | 2 ton anvil    |
| DTNTR   |      13.00 | Detonator      |
| FB      |      10.00 | Bird seed      |
| TNT2    |      10.00 | TNT (5 sticks) |
| ANV02   |       9.99 | 1 ton anvil    |
| OL1     |       8.99 | Oil can        |
| ANV01   |       5.99 | .5 ton anvil   |
| SLING   |       4.49 | Sling          |
| FU1     |       3.42 | Fuses          |
| FC      |       2.50 | Carrots        |
| TNT1    |       2.50 | TNT (1 stick)  |
+---------+------------+----------------+
14 rows in set (0.00 sec)

DESC关键字只应用于位于其前面的列名。上个例子只对prod_price降序,而prod_name还是升序排序。

与DESC相反的关键字是ASC(ASCENDING),可以用它来指定升序排序。但ASC没多大用,因为升序是默认的。

使用ORDER BY和LIMIT的组合,可以找出一个列中最大或最小的值:

mysql> SELECT prod_price
    -> FROM products
    -> ORDER BY prod_price DESC
    -> LIMIT 1;
+------------+
| prod_price |
+------------+
|      55.00 |
+------------+
1 row in set (0.00 sec)

prod_price DESC保证行是从最贵到最便宜,LIMIT 1告诉MySQL返回一行。

  • 在多个列上降序排序 如果想在多个列上降序排序,那需要对每个列都指定DESC关键字。
  • 区分大小写和排序顺序 对文本性的数据进行排序时,一般按字典(dictionary)序,不区分大小写,a等同于A。若想改变排序规则,请联系数据库管理员。
  • ORDER BY子句的位置 在给出ORDER BY子句时,必须保证它在FROM子句后。而LIMIT子句必须位于ORDER BY子句后。顺序不对将产生错误信息。