MySQL LIMIT Clause
The LIMIT clause restricts how many rows a query returns. Use it for "top 5" lists, for previews, and to split long results into pages. Combined with ORDER BY, it answers questions like who are the three highest scorers?
1. Syntax
SELECT ... FROM ... [WHERE ...] [ORDER BY ...]
LIMIT row_count;
LIMIT row_count OFFSET skip; -- skip rows first
LIMIT skip, row_count; -- same thing, MySQL short form
LIMIT offset, count, the opposite of the long form. LIMIT 10, 5 skips 10 rows and returns 5.2. Top N Rows
SELECT player, points FROM scores ORDER BY points DESC LIMIT 3;
Result: 3 rows
| player | points |
|---|---|
| Bruno | 9650 |
| Dev | 9650 |
| Hiro | 9100 |
Bruno and Dev both have 9,650 points. When sort values tie, their order is not guaranteed, so add a tie-breaker column to make results repeatable:
SELECT player, points FROM scores ORDER BY points DESC, player ASC LIMIT 3;
Result: 3 rows
| player | points |
|---|---|
| Bruno | 9650 |
| Dev | 9650 |
| Hiro | 9100 |
3. Why LIMIT Needs ORDER BY
Without ORDER BY, a table has no defined order: MySQL returns whichever rows are cheapest to read, which can change after updates, index changes or upgrades. LIMIT 3 alone means "any 3 rows", not "the first 3".
SELECT player FROM scores LIMIT 3; -- some 3 rows: don't rely on which
Result: 3 rows
| player |
|---|
| Aanya |
| Bruno |
| Chloe |
4. OFFSET and Pagination
LIMIT page_size OFFSET (page − 1) × page_size.SELECT player, points FROM scores ORDER BY points DESC, player LIMIT 4 OFFSET 0; -- page 1
Page 1
| player | points |
|---|---|
| Bruno | 9650 |
| Dev | 9650 |
| Hiro | 9100 |
| Felix | 8800 |
SELECT player, points FROM scores ORDER BY points DESC, player LIMIT 4 OFFSET 4; -- page 2
Page 2
| player | points |
|---|---|
| Aanya | 8120 |
| Isla | 7750 |
| Chloe | 7300 |
| Emma | 6800 |
SELECT player, points FROM scores ORDER BY points DESC, player LIMIT 8, 4; -- page 3, short form
Page 3
| player | points |
|---|---|
| Jonas | 6400 |
| Gita | 5900 |
Count the total to know how many pages there are:
SELECT COUNT(*) AS total_rows, CEIL(COUNT(*) / 4) AS pages FROM scores;
Result: 1 row
| total_rows | pages |
|---|---|
| 10 | 3 |
5. LIMIT 1: the Single Best Row
SELECT player, played_on FROM scores ORDER BY played_on DESC, player_id DESC LIMIT 1; -- most recent
Result: 1 row
| player | played_on |
|---|---|
| Jonas | 2026-03-05 |
SELECT player, points FROM scores WHERE country = 'IN' ORDER BY points LIMIT 1; -- lowest Indian score
Result: 1 row
| player | points |
|---|---|
| Gita | 5900 |
6. Top N per Group
LIMIT applies to the whole result, not to each group. For "best player per country" use a window function and filter on its rank:
SELECT country, player, points
FROM (
SELECT country, player, points,
ROW_NUMBER() OVER (PARTITION BY country ORDER BY points DESC) AS rn
FROM scores
) ranked
WHERE rn = 1
ORDER BY points DESC;
Result: 6 rows
| country | player | points |
|---|---|---|
| BR | Bruno | 9650 |
| IN | Dev | 9650 |
| JP | Hiro | 9100 |
| DE | Felix | 8800 |
| UK | Isla | 7750 |
| FR | Chloe | 7300 |
7. LIMIT in UPDATE and DELETE
A single number (no offset) is allowed in UPDATE and DELETE, usually with ORDER BY:
UPDATE scores SET points = points + 500 ORDER BY points ASC LIMIT 2; -- boost the two lowest
SELECT player, points FROM scores ORDER BY points LIMIT 3;
Result: 3 rows
| player | points |
|---|---|
| Gita | 6400 |
| Emma | 6800 |
| Jonas | 6900 |
DELETE FROM scores ORDER BY played_on, player_id LIMIT 1;
SELECT COUNT(*) AS players_left FROM scores;
Result: 1 row
| players_left |
|---|
| 9 |
8. LIMIT in Sub-queries
MySQL doesn't allow LIMIT inside an IN (…) sub-query:
SELECT player FROM scores WHERE player_id IN (SELECT player_id FROM scores ORDER BY points DESC LIMIT 3);
ERROR 1235 (42000): This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
Wrap it in a derived table instead:
SELECT s.player, s.points
FROM scores s
JOIN (SELECT player_id FROM scores ORDER BY points DESC LIMIT 3) top3 USING (player_id)
ORDER BY s.points DESC;
Result: 3 rows
| player | points |
|---|---|
| Bruno | 9650 |
| Dev | 9650 |
| Hiro | 9100 |
9. Fast Pagination for Big Tables (Keyset)
OFFSET 100000 forces MySQL to read and throw away 100,000 rows, so deep pages get slower and slower. Keyset pagination remembers the last row shown and continues after it, using an index:
-- page 1
SELECT player_id, player FROM scores ORDER BY player_id LIMIT 3;
Result: 3 rows
| player_id | player |
|---|---|
| 2 | Bruno |
| 3 | Chloe |
| 4 | Dev |
-- next page: continue after the last player_id shown (4)
SELECT player_id, player FROM scores WHERE player_id > 4 ORDER BY player_id LIMIT 3;
Result: 3 rows
| player_id | player |
|---|---|
| 5 | Emma |
| 6 | Felix |
| 7 | Gita |
| OFFSET pagination | Keyset pagination | |
|---|---|---|
| Jump to page 50 | Yes | No, only next / previous |
| Speed on deep pages | Gets slower | Constant |
| Stable when rows are inserted | Rows can shift or repeat | Stable |
10. Pagination from Java
int pageSize = 4, page = 2;
String sql = "SELECT player, points FROM scores ORDER BY points DESC, player LIMIT ? OFFSET ?";
try (PreparedStatement ps = con.prepareStatement(sql)) {
ps.setInt(1, pageSize);
ps.setInt(2, (page - 1) * pageSize);
try (ResultSet rs = ps.executeQuery()) {
while (rs.next()) System.out.println(rs.getString(1) + " " + rs.getInt(2));
}
}
// Spring Data: repository.findAll(PageRequest.of(page - 1, pageSize, Sort.by("points").descending()))
11. Summary
LIMIT nreturns at most n rows;LIMIT n OFFSET m(orLIMIT m, n) skips m first.- Always pair LIMIT with ORDER BY, plus a tie-breaker, for predictable results.
- Page k of size n:
LIMIT n OFFSET (k − 1) × n; use keyset pagination for large tables. - For top-N per group use ROW_NUMBER(); LIMIT isn't allowed in IN sub-queries.