(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Cómo paginar resultados en SQL Server con OFFSET FETCH

João Barros 05 de July de 2026 4 min de lectura

Cuando una consulta en SQL Server devuelve miles de filas, mostrarlas todas a la vez es poco práctico: es mejor dividir los datos en páginas. La forma más sencilla y legible de paginar resultados en SQL Server es la cláusula OFFSET FETCH, disponible desde SQL Server 2012 y también en Azure SQL Database. A continuación tienes un ejemplo práctico, paso a paso, y el error más común que debes evitar. OFFSET indica cuántas filas saltar y FETCH cuántas devolver a continuación.

Requisitos previos

  • Una instancia de SQL Server 2012 o superior (también funciona en Azure SQL Database).
  • SQL Server Management Studio (SSMS) o Azure Data Studio para ejecutar las consultas.
  • Una tabla con varios registros para probar — en el ejemplo usamos dbo.Encomendas.
  • Nociones básicas de SELECT y ORDER BY.

Paso 1: Entender por qué el ORDER BY es obligatorio

La cláusula OFFSET FETCH funciona en dos fases: primero "salta" un número de filas y luego "trae" las filas siguientes. Para que saltar y traer tengan sentido, SQL Server necesita un orden bien definido — por eso el OFFSET solo puede aparecer después de un ORDER BY. Sin ordenación, el motor no garantiza qué fila va primero y la paginación sería impredecible.

Error común: escribir OFFSET sin ORDER BY. En ese caso SQL Server devuelve un error de sintaxis, porque el OFFSET forma parte de la propia cláusula ORDER BY. Ordena siempre antes de saltar filas.

Paso 2: Conocer la sintaxis OFFSET FETCH

La estructura es siempre la misma: ordenas, saltas con OFFSET y traes un bloque con FETCH NEXT. Este ejemplo devuelve los 10 pedidos más recientes:

SELECT EncomendaID, Cliente, DataEncomenda, Total
FROM dbo.Encomendas
ORDER BY DataEncomenda DESC, EncomendaID DESC
OFFSET 0 ROWS
FETCH NEXT 10 ROWS ONLY;

OFFSET 0 ROWS significa "no saltes ninguna fila" y FETCH NEXT 10 ROWS ONLY significa "trae solo las 10 siguientes". Las palabras ROWS/ROW y NEXT/FIRST son sinónimos — elige las que hagan la consulta más legible.

Paso 3: Calcular la página con una fórmula sencilla

Para saltar a cualquier página solo necesitas dos valores: el número de página y el tamaño de página. El número de filas a saltar es (página - 1) * tamaño. Este ejemplo muestra la página 3, con 10 registros por página, es decir, salta las primeras 20 filas:

DECLARE @Pagina  INT = 3;
DECLARE @Tamanho INT = 10;

SELECT EncomendaID, Cliente, DataEncomenda, Total
FROM dbo.Encomendas
ORDER BY DataEncomenda DESC, EncomendaID DESC
OFFSET (@Pagina - 1) * @Tamanho ROWS
FETCH NEXT @Tamanho ROWS ONLY;

Cambiando solo el valor de @Pagina a 1, 2, 3… recorres todos los resultados, bloque a bloque. Es exactamente el patrón que se ejecuta detrás de una tabla con botones "Anterior" y "Siguiente" o de una API que devuelve datos paginados. Mantén @Tamanho igual en todas las páginas para que la navegación sea consistente.

Paso 4: Ordenar por una columna única para una paginación estable

Si ordenas solo por una columna con valores repetidos (por ejemplo, solo por DataEncomenda), dos pedidos con la misma fecha pueden intercambiar posiciones entre ejecuciones y acabar en la página equivocada — o aparecer dos veces. La solución es añadir siempre una columna única como criterio de desempate, normalmente la clave primaria:

ORDER BY DataEncomenda DESC, EncomendaID DESC

Con un desempate único, el orden pasa a ser determinista y cada fila aparece exactamente en una página.

Comprobar el resultado

Ejecuta la consulta con @Pagina = 1 y después con @Pagina = 2: cada una debe devolver 10 filas y no puede haber ningún registro repetido entre las dos páginas. Para saber cuántas páginas existen en total, divide el número de filas por el tamaño de página y redondea hacia arriba:

DECLARE @Tamanho INT = 10;

SELECT CEILING(COUNT(*) * 1.0 / @Tamanho) AS TotalPaginas
FROM dbo.Encomendas;

Si la última página trae menos de 10 filas, todo está correcto: es simplemente el resto de los registros.

Conclusión

Con ORDER BY más OFFSET FETCH obtienes una paginación legible, estandarizada y fácil de mantener, ideal para alimentar tablas de la interfaz y APIs. Para páginas muy profundas — cuando saltas decenas de miles de filas — el OFFSET puede volverse lento; en ese escenario conviene estudiar la keyset pagination, que pagina a partir de la última clave leída. Este enfoque forma parte del estándar ANSI SQL, por lo que el mismo razonamiento se aplica a otros motores como PostgreSQL. Un buen próximo paso es crear un índice por las columnas de tu ORDER BY y comparar el tiempo de respuesta. ¿Cuál de tus consultas más pesadas paginarías primero?