# Skip / Take (paging)

> Page a query with Skip(n) (OFFSET) and Take(m) (LIMIT). The count can be a compile-time constant OR a runtime integer — a variable, parameter, or expression — so a page size chosen at runtime works directly.

<!-- id: query-paging · area: query · stability: stable · html: https://osysharp.com/reference/query/paging/ -->

## Summary        {#summary}
`Take(m)` limits a query to the first `m` rows; `Skip(n)` skips the first `n`. Together they page a result set
(`Skip(n).Take(m)`). The count for either can be a **compile-time constant** (`Take(20)`) **or a runtime
integer** — a variable, a parameter, or any int expression (`Take(pageSize)`) — exactly like the parameterized
`LIMIT`/`OFFSET` a database query uses. Order the query first (`OrderBy`) so paging is deterministic.

## Signature      {#signature}
```osy syntax
set.Where(p).OrderBy(k).Skip(<int>).Take(<int>).ToList()
//                       └ OFFSET      └ LIMIT   (each count: a constant OR a runtime int)
```

## Description    {#description}
- **`Take(m)`** returns at most the first `m` rows (SQL `LIMIT`). **`Skip(n)`** discards the first `n` rows
  (SQL `OFFSET`). `Skip(n).Take(m)` is the page-(n/m) window.
- **The count may be runtime.** `Take(pageSize)` / `Skip(page * pageSize)` accept an int **variable, parameter,
  or expression** — not just a literal. The value is read when the query runs (like a bound SQL parameter), so a
  page size the caller chose at runtime just works.
- **The count must be an integer.** A non-integer argument is a compile error.
- **Take never throws and never over-returns.** Asking for more rows than exist returns all of them; `Take(0)`
  returns none — matching C#.
- **Order first for determinism.** Without an `OrderBy`, the database may return any rows; page a *sorted* query.
- **What it composes with.** `Where`, [`OrderBy`/`ThenBy`](https://osysharp.com/reference/query/ordering/), [`Include`](https://osysharp.com/reference/query/include/), `Distinct`,
  and the single-row terminals. **`Skip` may not precede a [`Select`](https://osysharp.com/reference/query/select/) projection** — `Take` may, and
  `Skip` may not (page first and project after, or project into a `class` and page the result). Neither may precede a
  [`GroupBy`](https://osysharp.com/reference/query/group-by/): only `Where` may.

## Examples       {#examples}
```osy title="paging with a runtime page size" test app=query-paging
entity Order {
  [Required] string Name;
  decimal Total;
}

// The page and size are PARAMETERS — chosen by the caller at runtime.
Order[] PageOrders(int page, int size) {
  return Order
    .OrderByDescending(o => o.Total)
    .Skip(page * size)
    .Take(size)
    .ToList();
}

// A constant count still works exactly as before.
Order[] TopFive() {
  return Order.OrderByDescending(o => o.Total).Take(5).ToList();
}

// Take clamps: n larger than the row count returns all rows; 0 returns none.
int HowMany(int n) {
  var rows = Order.OrderBy(o => o.Name).Take(n).ToList();
  return rows.Count;
}
```

## See also       {#see-also}
- [Union / Concat / Intersect / Except](https://osysharp.com/reference/query/set-operators/) — Union / Concat / Intersect / Except over paged query sets
- [List OrderBy (in-memory)](https://osysharp.com/reference/function/list-orderby/) — OrderBy / Take on an in-memory `List<T>` (not a database set)
