DevLearningTools

LEARN · SQL

SQL OFFSET

OFFSET skips a number of rows before a query starts returning results, the other half of pagination alongside LIMIT/TOP. Learn the syntax across all six databases, and why large offsets get slow.

The previous lesson capped how many rows come back. OFFSET answers a different question: how many rows to skip before returning any at all, the mechanism behind "page 2," "page 3," and so on.

Learning Objectives

  • Skip a number of rows with OFFSET, in the syntax specific to the database you're using.
  • Combine OFFSET with a row limit to build pagination.
  • Understand why a large OFFSET gets slower as it grows, and what the alternative is.

Full Ordered Result

Every matching row, sorted

OFFSET 20

First 20 rows skipped

LIMIT / FETCH NEXT

Then capped to a page size

Page 3

Rows 21-30, for example

OFFSET by Database

DatabaseSyntax
MySQL / MariaDB / PostgreSQL / SQLiteLIMIT 10 OFFSET 20
SQL Server / Oracle 12c+OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY
Oracle, pre-12cNo OFFSET keyword, needs a double-nested ROWNUM subquery
MySQL / MariaDB / PostgreSQL / SQLite
SELECT first_name, salary
FROM employees
ORDER BY id
LIMIT 10 OFFSET 20;

-- Skips the first 20 rows, then returns the next 10 (page 3, 10 per page)
SQL Server / Oracle 12c+ (ANSI standard)
SELECT first_name, salary
FROM employees
ORDER BY id
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY;
NOTE

SQL Server's TOP keyword has no offset equivalent at all, TOP alone can only ever take the first N rows, never skip ahead, pagination on SQL Server requires this OFFSET ... ROWS FETCH NEXT ... ROWS ONLY form instead.

Oracle Pre-12c: No OFFSET Keyword

Older Oracle has no OFFSET keyword at all. The workaround nests three queries inside each other (a technique called a subquery, covered in full in Module 6, don't worry about fully following the syntax here yet): the innermost query sorts the data, the middle query assigns ROWNUM to that already-sorted result, and the outer query filters that ROWNUM range. All three levels matter, ROWNUM has to be assigned after sorting, not before, or the "rows" being numbered wouldn't be in the right order to begin with.

Oracle, pre-12c
SELECT first_name, salary FROM (
  SELECT first_name, salary, ROWNUM AS rn FROM (
    SELECT first_name, salary FROM employees ORDER BY id
  )
)
WHERE rn > 20 AND rn <= 30;
NOTE

This is historical knowledge more than a live concern today. Oracle 12c was released in 2013, over a decade ago, so any actively maintained Oracle database in production today almost certainly already supports the modern OFFSET ... FETCH NEXT syntax. The ROWNUM technique is worth recognizing if it shows up in old code or an interview question, not something you'd reach for by default on a current Oracle instance.

Why a Large OFFSET Gets Slow

OFFSET doesn't skip rows for free. The database still has to scan through and discard every row before the offset, it just doesn't send them back to you. Page 2 with OFFSET 10 is cheap. Page 10,000 with OFFSET 100000 means scanning and discarding 100,000 rows on every single request, which gets measurably slower as the offset grows, even though the page size never changes.

NOTE

The standard alternative for deep pagination is keyset pagination (also called cursor-based pagination): instead of OFFSET 100000, filter with WHERE id > last_seen_id ORDER BY id LIMIT 10. The database can jump straight there using an index on id, instead of scanning everything before it. This is beyond what a beginner needs to implement immediately, but worth knowing the name of for when OFFSET's performance actually becomes a problem.

Try It Yourself

Write a query returning page 2 of employees, 5 per page, ordered by id, for MySQL.

Answer
SELECT first_name
FROM employees
ORDER BY id
LIMIT 5 OFFSET 5;

-- Page 1 would be LIMIT 5 OFFSET 0 (rows 1-5)
-- Page 2 skips those 5, returning the next 5 (rows 6-10)

Frequently Asked Questions

Does OFFSET require ORDER BY?

Not syntactically, a database won't reject OFFSET without ORDER BY, but without it, which rows get skipped and returned isn't guaranteed to be consistent between requests. Always pair OFFSET with ORDER BY for predictable pagination.

Can OFFSET be used without a row limit, just to skip rows and return everything else?

On MySQL and PostgreSQL, OFFSET can technically be used alone, though MySQL requires a very large LIMIT value alongside it in practice. SQL Server and Oracle's OFFSET ... FETCH NEXT syntax requires both parts together. In practice, OFFSET is almost always paired with a row limit anyway, since "skip some, then return literally everything else" is rarely the actual goal.

Common Beginner Mistakes

Using OFFSET without ORDER BY and expecting consistent pages

Without an explicit sort, the database is free to return rows in whatever order is most efficient internally, which can change between requests. A user could see the same row twice across two pages, or miss one entirely. Always pair OFFSET with ORDER BY.

Using a large OFFSET for deep pagination and being surprised it's slow

OFFSET 100000 still has to scan and discard 100,000 rows internally, it isn't a free jump to that position. For deep pagination at scale, keyset pagination (filtering by WHERE id > last_seen_id) performs far better.

Best Practices

  • Always pair OFFSET with an explicit ORDER BY, never rely on a database's incidental default ordering for pagination.
  • Sort by a column with mostly-unique values (like id) as a tiebreaker, so page boundaries stay stable even when the main sort column repeats.
  • For deep pagination over large tables, reach for keyset pagination (WHERE id > last_seen_id) instead of a large OFFSET once performance actually matters.
  • Know your target database's exact syntax, OFFSET is not interchangeable with SQL Server/Oracle's OFFSET ... FETCH NEXT or Oracle pre-12c's ROWNUM subquery.

Interview Questions

Write a query returning the 3rd page of employees, 10 per page, ordered by salary descending, for PostgreSQL.

SELECT first_name, salary FROM employees ORDER BY salary DESC LIMIT 10 OFFSET 20; — page 1 is OFFSET 0, page 2 is OFFSET 10, page 3 is OFFSET 20, each offset is (page number - 1) times the page size.

Why is OFFSET-based pagination considered inefficient at scale, and what's the standard alternative?

The database can't jump directly to row 1,000,000, it has to scan and discard every row before the offset, so the cost grows with how deep you page in. Keyset (cursor-based) pagination replaces OFFSET with a WHERE condition on the last row seen, letting the database use an index to jump straight there instead of scanning from the start.

How would you write page 2 (10 per page) pagination on SQL Server, and on Oracle 11g (pre-12c)?

SQL Server: SELECT first_name FROM employees ORDER BY id OFFSET 10 ROWS FETCH NEXT 10 ROWS ONLY; Oracle 11g has no OFFSET keyword at all, it needs a double-nested subquery: assign ROWNUM after sorting in an inner query, then filter that ROWNUM range in an outer WHERE clause.

Summary

This lesson covered OFFSET across all six databases, skipping rows before a limit applies to build pagination, Oracle's pre-12c double-nested ROWNUM workaround for databases with no OFFSET keyword, and why a large OFFSET gets slower as it grows, with keyset pagination as the standard fix once that matters.

That completes Module 1, SQL Basics: writing a query, filtering, sorting, inserting, updating, deleting, handling NULL, limiting results, and paginating through them, the core toolkit for reading and writing data in any SQL database.

What's Next?

Module 2, Operators and Filtering, is next, starting with what an operator actually is and the categories SQL groups them into, before AND, OR, NOT, LIKE, wildcards, IN, BETWEEN, and aliases.

</>

Ready to Practice SQL?

Write and run real SQL queries online, right in your browser, no install or signup required. Pick a playground based on which database you want to practice on.

SQLite / PostgreSQL

Fast, no server, no ads.

Open DB Fiddle ↗

MySQL / SQL Server

Switch databases with one dropdown.

Open SQL Fiddle ↗

Both open a third-party SQL playground in a new tab. External site terms and privacy policy apply.