MySQL LIMIT 子句
你已经学习了如何选择特定的列、使用 WHERE 过滤行,以及使用 ORDER BY 对结果进行排序。那么,如果你只需要其中一小部分结果,而不是整个列表呢?这就是 LIMIT 子句发挥作用的地方。它用于限制查询返回的行数,在实现分页、Top N(前 N 个)报告或单纯的数据抽样时非常有用。
1. 基础 LIMIT 用法
使用 LIMIT 最简单的方法是指定一个整数值。这会告诉 MySQL 准确返回这么多行,从匹配你的 SELECT 语句以及任何 WHERE 或 ORDER 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 仅从该排序列表中提取前五个城市。
| Name | CountryCode | Population |
|---|---|---|
| Seoul | KOR | 9981619 |
| Mumbai | IND | 10500000 |
| Shanghai | CHN | 9696300 |
| Mexico City | MEX | 8591309 |
| Jakarta | IDN | 9604919 |
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 M 和 LIMIT 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 行这两个查询都会产生类似以下的输出(同样,具体结果可能会略有不同):
| Name | CountryCode | Population |
|---|---|---|
| Delhi | IND | 9817439 |
| Karachi | PAK | 9269265 |
| Tokyo | JPN | 7980230 |
| Beijing | CHN | 7472000 |
| New York | USA | 8008278 |
这种模式是在 Web 应用程序中实现分页的基础,允许用户一页一页地浏览大型数据集。
3. 重要注意事项
3.1 ORDER BY 配合 LIMIT 至关重要
如果你使用了 LIMIT 却没有使用 ORDER BY 子句,那么返回结果的顺序是没有任何保证的。MySQL 可以按它认为最有效的任何顺序返回行。如果你需要一致、可预测的数据子集(比如“前 10 名”或“下一页”),你必须在应用 LIMIT 之前使用 ORDER BY 来建立明确的排序规则。
3.2 大偏移量的性能问题
虽然带有 OFFSET 的 LIMIT 非常适合分页,但要注意极大偏移量带来的性能影响。例如,LIMIT 10 OFFSET 1000000 意味着 MySQL 仍然需要遍历并识别前 1,000,010 行,然后丢弃前 1,000,000 行,最后才返回接下来的 10 行。在非常大的表上,这可能会变得很慢。对于极端的深度分页,通常有性能更好的替代策略(比如“键集分页 keyset pagination”或使用索引列上 WHERE 子句的“查找法 seek method”),但这是以后的高级主题。对于典型的日常用例,LIMIT 和 OFFSET 是完全没有问题的。
3.3 查询执行顺序
当 MySQL 处理带有 LIMIT 和 OFFSET 的 SELECT 语句时,通常遵循以下操作顺序:
- FROM 子句: 确定表
- WHERE 子句: 过滤行
- GROUP BY 子句: 对行进行分组聚合(如果存在)
- HAVING 子句: 过滤聚合后的组(如果存在)
- SELECT 子句: 确定要输出的列和表达式
- ORDER BY 子句: 对结果行进行排序
- LIMIT/OFFSET 子句: 选择排序后行的子集
这个执行流向表明,LIMIT/OFFSET 是在所有的过滤、分组和排序都完成之后,在最后阶段才被应用的。