Kodewick
第 4 课,共 21 课目录

排序、LIMIT 和 DISTINCT

第 4 课,共 21 课 · 第 1 部分 · 查数据 · 约 15 分钟

到现在为止,结果里行的顺序都是数据库自己定的。看起来像是按 id 排,可没人保证:换一个数据库、数据多了,顺序都可能变。想要确定的顺序,就加一个 ORDER BY:

main.sql
1SELECT name, price2FROM products3ORDER BY price;
输出
nameprice
笔记本4.50
中性笔(10 支)6.00
数据线8.50
咖啡杯9.90
帆布袋11.00
水杯12.00
手机壳15.00
台灯25.00
双肩包39.90
耳机59.00
10 行

ORDER BY

ORDER BY 列 按这一列从小到大排,写在 WHERE 后面。数字比大小,日期比早晚。按注册日期排的客户,最早的在前:

main.sql
1SELECT name, joined2FROM customers3ORDER BY joined;
输出
namejoined
林晓2025-01-12
王磊2025-02-03
陈静2025-02-20
张伟2025-03-15
刘洋2025-04-01
赵敏2025-05-18
孙强2025-06-09
周婷2025-07-21
吴昊2025-08-30
郑雪2025-09-14
10 行

从小到大叫升序,写 ASC;不写就是升序,所以 ORDER BY joined ASC 和上面一样。

从大到小:DESC

在列名后面加 DESC,就是降序,从大到小。最新的订单排在前面:

main.sql
1SELECT id, order_date, status2FROM orders3WHERE status = '已发货'4ORDER BY order_date DESC;
输出
idorder_datestatus
112025-10-22已发货
102025-10-20已发货
82025-10-12已发货
62025-10-03已发货
52025-10-01已发货
32025-09-18已发货
22025-09-05已发货
12025-09-02已发货
8 行

这条查询先用 WHERE 挑出已发货的订单,再把它们排序。排序用的列也不一定要选出来:ORDER BY stock 照样可以只显示 name。

文字怎么排

文字也能排序。英文按字母顺序;汉字按编码排,不是按拼音,也不是按笔画:

main.sql
1SELECT name2FROM products3ORDER BY name;
输出
name
中性笔(10 支)
双肩包
台灯
咖啡杯
帆布袋
手机壳
数据线
水杯
笔记本
耳机
10 行

「中」的编码最小,所以中性笔排第一;「耳」的编码最大,耳机排最后。想按拼音排,要另外设置,这门课不讲。

按几列排

ORDER BY 后面可以写好几列,用逗号隔开:先按第一列排,第一列一样的,再按第二列排。每一列可以有自己的 ASC 或 DESC:

main.sql
1SELECT name, category, price2FROM products3ORDER BY category, price DESC;
输出
namecategoryprice
水杯厨房12.00
咖啡杯厨房9.90
耳机数码59.00
台灯数码25.00
手机壳数码15.00
数据线数码8.50
中性笔(10 支)文具6.00
笔记本文具4.50
双肩包箱包39.90
帆布袋箱包11.00
10 行

同一个分类的商品排在一起,分类里面贵的在前。点单步,看 ORDER BY 把行重新排了一遍。

小技巧: 第一列有一样的值时,最好再加一列(比如 id)把顺序定死,不然这几行谁前谁后还是说不准。

前几名:LIMIT

LIMIT 3 只要结果的前 3 行,写在最后。和 ORDER BY 一起用,就是「前 3 名」。最贵的 3 件商品:

main.sql
1SELECT name, price2FROM products3ORDER BY price DESC4LIMIT 3;
输出
nameprice
耳机59.00
双肩包39.90
台灯25.00
3 行

点单步:先按价格从高到低排好,最后 LIMIT 只留下前 3 行。不写 ORDER BY 的 LIMIT 3 只是「随便 3 行」,没有意义。

LIMIT 是 MySQL 的写法(SQLite、PostgreSQL 也认)。别的数据库可能写成 FETCH FIRST 3 ROWS ONLY(标准写法),SQL Server 写成 SELECT TOP 3 …。

先猜一猜

结果是哪件商品?

1SELECT name, stock2FROM products3ORDER BY stock4LIMIT 1;

去掉重复:DISTINCT

客户来自哪些城市?直接查 city,同一个城市会出现好几次:

main.sql
1SELECT city2FROM customers;
输出
city
上海
北京
上海
广州
成都
北京
广州
上海
成都
杭州
10 行

SELECT DISTINCT 把一模一样的行只留一行:

main.sql
1SELECT DISTINCT city2FROM customers3ORDER BY city;
输出
city
上海
北京
广州
成都
杭州
5 行

「上」的编码比「北」小,所以上海排在北京前面。DISTINCT 后面写几列,就按这几列一起去重:两行要每一列都一样,才算重复。

练一练

写好查询,点检查。提示随便看,实在想不出来再看答案。

练习 1

库存最多的 3 件

查出库存最多的 3 件商品,显示 name 和 stock 两列,库存多的在前。

要显示
namestock
数据线200
笔记本120
中性笔(10 支)80
3 行
exercise1.sql
1SELECT name, stock2FROM products;
输出
点「运行」或按 Ctrl+Enter
练习 2

最新的待发货订单

查出待发货的订单,显示 id 和 order_date 两列,最新的在前。

要显示
idorder_date
122025-10-25
92025-10-15
72025-10-10
3 行
exercise2.sql
1SELECT id, order_date2FROM orders3ORDER BY order_date;
输出
点「运行」或按 Ctrl+Enter
练习 3

下过单的客户

订单表里出现过哪些客户编号?显示 customer_id 一列,每个编号只出现一次,从小到大。

要显示
customer_id
1
2
3
4
5
7
8
7 行
exercise3.sql
1SELECT customer_id2FROM orders;
输出
点「运行」或按 Ctrl+Enter

这一课学会了

  • 不写 ORDER BY,行的顺序没人保证;要确定的顺序就写 ORDER BY。
  • ASC 从小到大(不写就是它),DESC 从大到小;汉字按编码排,不按拼音。
  • ORDER BY a, b 先按 a 排,a 一样的再按 b 排;每列有自己的方向。
  • LIMIT n 只要前 n 行,和 ORDER BY 一起用就是「前 n 名」;别的数据库可能写 FETCH FIRST n ROWS ONLY 或 TOP n。
  • SELECT DISTINCT 去掉一模一样的行。