讲解

不指定顺序时,数据库返回行的顺序是不保证的——今天按插入顺序返回,明天索引变了顺序就可能变。只要结果顺序对你有意义,就必须显式写 ORDER BY:ORDER BY age 按年龄升序(ASC,默认),ORDER BY age DESC 按年龄降序。可以同时排多列:ORDER BY city, age DESC 先按城市排,城市相同再按年龄降序。

LIMIT 限制返回的行数:ORDER BY price DESC LIMIT 3 就是「最贵的三门课」。配合 OFFSET 可以跳过前面的行做分页:LIMIT 10 OFFSET 20 取第 21 到 30 行。分页是 LIMIT 最典型的用途,第 N 页(每页 10 条)就是 LIMIT 10 OFFSET (N-1)*10。

排序中 NULL 的位置值得留意:SQLite 把 NULL 视为最小值,所以升序时 NULL 排在最前、降序时排在最后。如果业务上要求 NULL 一律垫底,SQLite 和 PostgreSQL 支持 ORDER BY age DESC NULLS LAST 的写法;MySQL 不支持该语法,常用 ORDER BY age IS NULL, age DESC 这样的技巧实现。

示例

按价格从高到低排出最贵的三门课:

SELECT title, price FROM courses ORDER BY price DESC LIMIT 3;

分页演示:按下单日期排序后取「第二页」,每页 5 条:

SELECT id, order_date, amount FROM orders ORDER BY order_date, id LIMIT 5 OFFSET 5;

多列排序:先按班级,再按年龄从大到小:

SELECT name, class_name, age FROM students ORDER BY class_name, age DESC;

常见坑

  • 以为不写 ORDER BY 顺序也稳定:表数据的物理顺序是实现细节,删除、更新、重建索引都可能改变返回顺序。凡是要顺序的场景都显式排序,分页查询尤其必须排。
  • ASC/DESC 写反:DESC 是降序(从大到小),ASC 是升序(默认,可省略)。「最新订单」要用 ORDER BY order_date DESC,写反了就成了最旧订单。
  • OFFSET 大页码的性能:LIMIT 10 OFFSET 100000 意味着数据库要先数出十万行再丢弃,深分页会越来越慢。大数据量分页应考虑「记住上一页最后一行的排序键」的游标式分页。
  • 排序键不唯一导致分页错位:多行排序键相同时它们之间的顺序不稳定,翻页可能重复或遗漏。给 ORDER BY 追加唯一列(如主键 id)作「决胜列」就能保证稳定顺序。

小结

ORDER BY 控制顺序(DESC 降序、可多列、加唯一列保底),LIMIT/OFFSET 控制条数与分页;不排序就不要假设顺序。下一节学习去重:DISTINCT。