---
title: "OFFSET"
description: "The OFFSET clause skips a specified number of rows in a query's result set before returning the remaining rows, commonly used for pagination alongside LIMIT."
canonical: "https://motherduck.com/glossary/offset/"
related:
  - title: "RESULT | MotherDuck Docs"
    url: "https://motherduck.com/docs/sql-reference/motherduck-sql-reference/result/"
  - title: "DuckLake Architecture Deep Dive"
    url: "https://motherduck.com/blog/ducklake-architecture-deep-dive/"
  - title: "CREATE INDEX | MotherDuck Docs"
    url: "https://motherduck.com/docs/sql-reference/duckdb-sql-reference/duckdb-statements/create-index/"
gated_asset:
  title: "DuckLake on MotherDuck"
  url: "https://motherduck.com/product/ducklake/"
---

# OFFSET

> The OFFSET clause skips a specified number of rows in a query's result set before returning the remaining rows, commonly used for pagination alongside LIMIT.

## Overview
`OFFSET` tells a query how many rows to skip from the beginning of the (typically ordered) result set before it starts returning rows. On its own it's rarely used without `LIMIT` -- the pair together implement classic page-based pagination: "give me rows 21 through 30."

```sql
SELECT id, name
FROM customers
ORDER BY id
LIMIT 10 OFFSET 20;   -- skip the first 20 rows, return the next 10
```

## Why ORDER BY matters
Like `LIMIT`, `OFFSET` only produces a meaningful, repeatable result when the query has a deterministic `ORDER BY`. Without one, "the first 20 rows" is not well-defined, and different executions (or query plans) could skip a different set of rows.

## DuckDB notes
DuckDB implements the standard `LIMIT n OFFSET m` syntax and, like `LIMIT`, allows `OFFSET` to be an arbitrary expression rather than only a literal integer.

## Performance
`OFFSET` is conceptually simple but can be a performance trap at scale: to skip the first 1,000,000 rows, the database generally still has to produce and discard them, so `OFFSET` cost grows with its value. For deep pagination over large tables, a keyset (a.k.a. "seek") approach -- filtering with `WHERE` on the last row's sort key instead of using `OFFSET` -- avoids that cost:

```sql
-- instead of LIMIT 20 OFFSET 100000
SELECT id, name FROM customers
WHERE id > 100000   -- last id seen on the previous page
ORDER BY id
LIMIT 20;
```