MySQL 零基础教程

MySQL LIMIT 子句

你已经学习了如何选择特定的列、使用 WHERE 过滤行,以及使用 ORDER BY 对结果进行排序。那么,如果你只需要其中一小部分结果,而不是整个列表呢?这就是 LIMIT 子句发挥作用的地方。它用于限制查询返回的行数,在实现分页、Top N(前 N 个)报告或单纯的数据抽样时非常有用。

1. 基础 LIMIT 用法

使用 LIMIT 最简单的方法是指定一个整数值。这会告诉 MySQL 准确返回这么多行,从匹配你的 SELECT 语句以及任何 WHEREORDER BY 子句的第一行开始。

请记住,子句的顺序很重要。LIMIT 几乎总是放在 SELECT 语句的最后。

SELECT column1, column2
FROM your_table
WHERE condition
ORDER BY column1 DESC
LIMIT N; -- N 是要返回的最大行数

让我们看一个使用 world 数据库中 city(城市)表的例子。假设你想查看人口最多的五个城市。

SELECT Name, CountryCode, Population
FROM city
ORDER BY Population DESC
LIMIT 5;

这个查询首先将所有城市按人口降序排列,把最大的城市放在最前面。然后,LIMIT 5 仅从该排序列表中提取前五个城市。

NameCountryCodePopulation
SeoulKOR9981619
MumbaiIND10500000
ShanghaiCHN9696300
Mexico CityMEX8591309
JakartaIDN9604919

2. LIMIT 与 OFFSET:实现数据分页

通常,你不只是想要 N 个结果;你想要的是接下来的 N 个结果,或者是特定的一“页”结果。这就是 LIMIT 结合 OFFSET 发挥作用的地方。OFFSET 值告诉 MySQL 在开始返回结果之前要跳过多少行。

语法是 LIMIT N OFFSET M,其中 N 是要返回的行数,M 是要跳过的行数。

SELECT column1, column2
FROM your_table
WHERE condition
ORDER BY column1 ASC
LIMIT N OFFSET M; -- 在跳过 M 行之后,返回 N 行

或者,你可以使用简写形式 LIMIT M, N。意思是“跳过 M 行,然后返回 N 行”。

SELECT column1, column2
FROM your_table
WHERE condition
ORDER BY column1 ASC
LIMIT M, N; -- 跳过 M 行,返回 N 行

LIMIT N OFFSET MLIMIT M, N 都能达到相同的结果。选择你觉得更具可读性的一种。大多数开发者在熟悉之后,为了简洁,更喜欢使用 LIMIT M, N

让我们再次用 city 表来演示。我们已经找到了排名前 5 的最大城市。现在,让我们寻找接下来的 5 个最大城市(即按人口排名第 6 到第 10 的城市)。

SELECT Name, CountryCode, Population
FROM city
ORDER BY Population DESC
LIMIT 5 OFFSET 5; -- 跳过前 5 行,然后返回接下来的 5 行

或者使用简写:

SELECT Name, CountryCode, Population
FROM city
ORDER BY Population DESC
LIMIT 5, 5; -- 跳过 5 行,返回 5 行

这两个查询都会产生类似以下的输出(同样,具体结果可能会略有不同):

NameCountryCodePopulation
DelhiIND9817439
KarachiPAK9269265
TokyoJPN7980230
BeijingCHN7472000
New YorkUSA8008278

这种模式是在 Web 应用程序中实现分页的基础,允许用户一页一页地浏览大型数据集。

3. 重要注意事项

3.1 ORDER BY 配合 LIMIT 至关重要

如果你使用了 LIMIT 却没有使用 ORDER BY 子句,那么返回结果的顺序是没有任何保证的。MySQL 可以按它认为最有效的任何顺序返回行。如果你需要一致、可预测的数据子集(比如“前 10 名”或“下一页”),你必须在应用 LIMIT 之前使用 ORDER BY 来建立明确的排序规则。

3.2 大偏移量的性能问题

虽然带有 OFFSETLIMIT 非常适合分页,但要注意极大偏移量带来的性能影响。例如,LIMIT 10 OFFSET 1000000 意味着 MySQL 仍然需要遍历并识别前 1,000,010 行,然后丢弃前 1,000,000 行,最后才返回接下来的 10 行。在非常大的表上,这可能会变得很慢。对于极端的深度分页,通常有性能更好的替代策略(比如“键集分页 keyset pagination”或使用索引列上 WHERE 子句的“查找法 seek method”),但这是以后的高级主题。对于典型的日常用例,LIMITOFFSET 是完全没有问题的。

3.3 查询执行顺序

当 MySQL 处理带有 LIMITOFFSETSELECT 语句时,通常遵循以下操作顺序:

  1. FROM 子句: 确定表
  2. WHERE 子句: 过滤行
  3. GROUP BY 子句: 对行进行分组聚合(如果存在)
  4. HAVING 子句: 过滤聚合后的组(如果存在)
  5. SELECT 子句: 确定要输出的列和表达式
  6. ORDER BY 子句: 对结果行进行排序
  7. LIMIT/OFFSET 子句: 选择排序后行的子集

这个执行流向表明,LIMIT/OFFSET 是在所有的过滤、分组和排序都完成之后,在最后阶段才被应用的。