排序与截取 · SQL 与数据库
怎么给结果排序、截取、去重?
课程目录为什么需要它
一页搜索结果就是排好序、截取过的列表:最便宜的十个航班,最新的帖子排在最前。没有 ORDER BY 时,数据库可以按任何顺序返回行,而且每次都可能不一样。
直觉理解
把查询想成一条流水线,顺序是:
FROM选表WHERE扔掉不要的行SELECT选列,也可以算出新列ORDER BY给剩下的排序LIMIT只留前几行
AS 给算出来的列起名字,DISTINCT 去掉重复的行。
定义
ORDER BY 排序
Sorts rows by one or more columns, ascending (`ASC`, the default) or descending (`DESC`). Ties are broken by the next column listed.按一列或多列排序,升序(`ASC`,默认)或降序(`DESC`)。前一列相同时,按后面列出的列继续排。
LIMIT
Returns at most this many rows. `LIMIT 3 OFFSET 3` skips three rows first, which is how page 2 of a list works.最多返回这么多行。`LIMIT 3 OFFSET 3` 先跳过三行,列表的第 2 页就是这么做的。
示例
价格前三
在互动课里运行从贵到便宜排序,再留三行。
SELECT name, price
FROM products
ORDER BY price DESC
LIMIT 3;输出
name | price Backpack | 25.0 Lamp | 18.0 Mug | 6.0
逐步执行
- L3DESC:大的在前。Backpack 25.0、Lamp 18.0、Mug 6.0……
- L4三行之后就停。
Backpack, Lamp, Mug
计算列与 DISTINCT
在互动课里运行price * 1.2 对每一行都算一次,用 AS 起名字。DISTINCT 把五个类别变成三个。
SELECT name, price * 2 AS two_of_them
FROM products
WHERE category = 'home';
SELECT DISTINCT category FROM products ORDER BY category;输出
name | two_of_them Lamp | 36.0 Mug | 12.0 category bags home paper
逐步执行
- L1这个新列只存在于结果里,表本身没变。
Lamp 36.0, Mug 12.0 - L5bags、home、paper:各一次,按字母排序。
常见错误
依赖默认顺序
行的返回顺序是数据库觉得最快的顺序。只要顺序重要,就每次都写 ORDER BY。
以为 LIMIT 先执行
LIMIT 永远最后执行。ORDER BY price LIMIT 1 是所有商品里最便宜的那个,而不是随便拿一行再排序。
小测验
1. 这段代码会输出什么?
SELECT name FROM customers ORDER BY name DESC LIMIT 2;查看答案
答案:A
DESC 从 Z 到 A 排:Eli、Dana、Chen、Bo、Ada。LIMIT 留前两个。
2. 这段代码会输出什么?
SELECT DISTINCT day FROM orders WHERE qty < 3 ORDER BY day;查看答案
答案:A
订单 3、4、5、6 的数量小于 3。其中两个都在 2025-03-05,DISTINCT 只留一个。
动手练习
3 道练习,分三层:先预测程序的输出,再按新需求改程序,最后从零写一个。代码在浏览器里运行,提交马上判题。
- 预测输出按两列排序
准确写出查询结果。
- 改需求最新的在前
修改查询,返回最近的 3 笔订单,最新的在前。列保持不变。
- 从零写含税价
返回每件商品的
name,以及加 10% 税后的价格,列名叫with_tax(price × 1.1),便宜的在前。
本课术语
| 术语 | 中文 | 英文定义 |
|---|---|---|
| Ascending (ASC) | 升序 | From small to large, A to Z, old to new. |
| Descending (DESC) | 降序 | From large to small, Z to A, new to old. |
| Alias (AS) | 别名 | A new name for a column or table, valid inside one query. |