🙏 ¡Necesitamos tu ayuda! SQLtest.online no tiene anuncios y vive solo de donaciones. Incluso una pequeña cantidad ayuda. Donar ahora →
Código SQL copiado al portapapeles

SQL TOP, FETCH FIRST y WITH TIES

Lección 2.9 · Tiempo de lectura: ~9 min · Tareas de práctica ↓

SQL TOP y FETCH FIRST n ROWS ONLY son las alternativas a LIMIT: TOP lo usa SQL Server, y FETCH FIRST es el estándar SQL que admiten PostgreSQL, Oracle, MariaDB y otros. En esta lección aprenderás la sintaxis estándar, la paginación con OFFSET ... FETCH, la opción WITH TIES, que conserva las filas con valores iguales, PERCENT y las formas antiguas de Oracle y Firebird.

En la lección 2.7 limitaste resultados con LIMIT y OFFSET. Esa sintaxis funciona en MySQL, MariaDB, PostgreSQL y SQLite, pero SQL Server y Oracle no la aceptan. Cuando cambias de base de datos, lees consultas ajenas o preparas una entrevista, encontrarás varias formas más de escribir la misma idea.

Limitar filas en distintas bases de datos: LIMIT, TOP de SQL Server y el estándar FETCH FIRST; FETCH FIRST 3 ROWS WITH TIES devuelve cinco películas porque otras dos comparten la última duración

Por qué limitar filas tiene varias sintaxis

Durante mucho tiempo, limitar filas no formaba parte del estándar SQL, así que cada base de datos inventó su propia sintaxis:

  • MySQL y PostgreSQL añadieron LIMIT, y SQLite lo copió.
  • SQL Server añadió TOP.
  • Oracle tenía la pseudocolumna ROWNUM.
  • Firebird añadió FIRST y SKIP.

La cláusula estándar FETCH FIRST apareció recién en SQL:2008, cuando estas costumbres ya estaban establecidas. Hoy la mayoría de las bases de datos admiten la forma estándar además de la propia, pero MySQL y SQLite todavía no.


FETCH FIRST n ROWS ONLY: la sintaxis estándar

FETCH FIRST va después de ORDER BY, donde iría LIMIT:

SELECT title, length
FROM film
ORDER BY length
FETCH FIRST 3 ROWS ONLY;

Resultado: tres de las películas más cortas, de 46 minutos. La consulta funciona en MariaDB 10.6+, PostgreSQL y Oracle; MySQL da un error de sintaxis.

Las palabras FIRST y NEXT, ROW y ROWS son intercambiables: FETCH NEXT 1 ROW ONLY significa lo mismo que FETCH FIRST 1 ROWS ONLY. Elige la que se lea mejor. Si omites el número, FETCH FIRST ROW ONLY devuelve una fila.

Paginación con OFFSET ... FETCH NEXT

La forma estándar de OFFSET se escribe con la palabra ROWS y va antes de FETCH:

SELECT title, length
FROM film
ORDER BY length, title
OFFSET 10 ROWS
FETCH NEXT 5 ROWS ONLY;

Resultado: las películas 11 a 15 por duración, igual que LIMIT 5 OFFSET 10.

Es la única forma de paginar en SQL Server, y allí exige ORDER BY: OFFSET sin ordenación es un error de sintaxis.


WITH TIES: conservar las filas que comparten el último valor

Mira otra vez las películas más cortas. Cinco películas duran 46 minutos, pero FETCH FIRST 3 ROWS ONLY devuelve solo tres, y cuáles tres lo decide la base de datos.

WITH TIES lo resuelve: devuelve las primeras N filas más todas las filas siguientes que tienen los mismos valores de ordenación que la fila N.

SELECT title, length
FROM film
ORDER BY length
FETCH FIRST 3 ROWS WITH TIES;

Resultado: 5 filas. Se devuelven las cinco películas de 46 minutos, porque la tercera comparte su duración con otras dos.

OpciónFilasQué obtienes
FETCH FIRST 3 ROWS ONLY3tres cualesquiera de las cinco películas de 46 minutos
FETCH FIRST 3 ROWS WITH TIES5las cinco películas de 46 minutos

WITH TIES responde con honestidad a preguntas como «las tres películas más cortas»: ninguna película queda fuera solo porque comparte un valor con la última.

Reglas de WITH TIES

  • Exige ORDER BY: los empates se definen por las columnas de ordenación. Sin ordenación, PostgreSQL y MariaDB dan un error.
  • Una columna de desempate elimina los empates. Con ORDER BY length, title no hay dos filas iguales, y WITH TIES devuelve exactamente 3 filas.
  • El resultado puede ser mucho mayor que N. Las películas más largas de Sakila duran 185 minutos, y ORDER BY length DESC FETCH FIRST 3 ROWS WITH TIES devuelve 10 películas.

La misma consulta en PostgreSQL sobre la base de datos Bookings encuentra las rutas más largas:

SELECT flight_no, departure_city, arrival_city, duration
FROM routes
ORDER BY duration DESC
FETCH FIRST 3 ROWS WITH TIES;

Resultado: 4 rutas de 8 horas y 50 minutos: vuelos entre Moscú y Yuzhno-Sajalinsk o Petropávlovsk.

WITH TIES en FETCH lo admiten PostgreSQL 13+, MariaDB 10.6+ y Oracle 12c+.


SQL Server: TOP

SQL Server coloca TOP justo después de SELECT:

SELECT TOP (3) Name, ListPrice
FROM Product
ORDER BY ListPrice DESC;

Resultado: tres de los productos más caros de AdventureWorks.

Los paréntesis son opcionales para un número (TOP 3 también funciona), pero se recomiendan: con ellos TOP acepta además una variable o una expresión, como TOP (@n).

TOP tiene su propio WITH TIES, y allí solo funciona con TOP: OFFSET ... FETCH en SQL Server no admite WITH TIES.

SELECT TOP (3) WITH TIES Name, ListPrice
FROM Product
ORDER BY ListPrice DESC;

Resultado: 5 productos. Cinco tallas de la bicicleta Road-150 Red cuestan 3578.27.

Trampas de TOP

  • TOP sin ORDER BY está permitido, pero devuelve filas arbitrarias, igual que LIMIT sin ordenación.
  • TOP ... WITH TIES sin ORDER BY es un error.
  • SQL Server no acepta FETCH FIRST por sí solo: FETCH solo se permite después de OFFSET. Para las primeras filas escribe OFFSET 0 ROWS FETCH NEXT 3 ROWS ONLY o usa TOP.

Devolver un porcentaje de filas

A veces no necesitas 10 filas sino el 10% de ellas. SQL Server y Oracle pueden hacerlo directamente:

SELECT TOP (1) PERCENT Name, ListPrice
FROM Product
ORDER BY ListPrice DESC;

Resultado: 3 filas. El 1% de 295 productos es 2,95, y SQL Server redondea hacia arriba.

En Oracle se usa la forma estándar:

SELECT first_name, last_name, salary
FROM hr.employees
ORDER BY salary DESC
FETCH FIRST 5 PERCENT ROWS ONLY;

Resultado: los 6 empleados con los salarios más altos: el 5% de 107 es 5,35, redondeado hacia arriba.

DuckDB escribe el porcentaje en LIMIT: LIMIT 10%. PostgreSQL, MariaDB y MySQL no admiten porcentajes: allí primero cuentas las filas y calculas el número tú mismo.


Oracle: ROWNUM y FETCH FIRST

Antes de la versión 12c Oracle no tenía FETCH FIRST, y el código antiguo limita filas con la pseudocolumna ROWNUM. Numera las filas a medida que se leen, antes de aplicar ORDER BY. Por eso esta consulta es incorrecta:

SELECT first_name, last_name, salary
FROM hr.employees
WHERE ROWNUM <= 3
ORDER BY salary;

Resultado: no los tres salarios más bajos, sino las tres primeras filas que leyó la base de datos (17000, 17000 y 24000), ordenadas después.

Para ordenar primero, el código antiguo envuelve la consulta ordenada en una subconsulta y aplica ROWNUM a su resultado:

SELECT first_name, last_name, salary
FROM (
    SELECT first_name, last_name, salary
    FROM hr.employees
    ORDER BY salary
)
WHERE ROWNUM <= 3;

Resultado: los tres salarios más bajos: 2100, 2200 y 2200.

Otra trampa: WHERE ROWNUM > 1 no devuelve ninguna fila. La primera fila recibe el número 1, no cumple la condición y se descarta; la siguiente vuelve a ser la número 1, y así sucesivamente.

En Oracle 12c y posteriores usa simplemente FETCH FIRST, incluido WITH TIES:

SELECT first_name, last_name, salary
FROM hr.employees
ORDER BY salary DESC
FETCH FIRST 7 ROWS WITH TIES;

Resultado: 8 empleados: el 7.º y el 8.º ganan 12008.

Oracle sigue sin aceptar LIMIT, incluso en la versión 26ai.


Firebird: FIRST, SKIP y ROWS

Firebird tiene dos sintaxis propias. FIRST y SKIP van justo después de SELECT, como TOP:

SELECT FIRST 3 SKIP 2 first_name, last_name, salary
FROM employee
ORDER BY salary DESC;

Resultado: los empleados 3 a 5 por salario: se omiten dos filas y se devuelven tres.

ROWS m TO n va al final de la consulta y recibe números de fila en lugar de una cantidad:

SELECT first_name, last_name, salary
FROM employee
ORDER BY salary DESC
ROWS 3 TO 5;

Resultado: los mismos empleados 3 a 5. ROWS 3 solo significa las tres primeras filas.

Desde Firebird 3.0 también funciona el estándar OFFSET ... FETCH. WITH TIES no se admite, ni siquiera en Firebird 5.


WITH TIES en MySQL y SQLite

MySQL y SQLite no tienen ni FETCH ni WITH TIES, pero el mismo resultado se puede construir con herramientas que aprenderás más adelante en el curso. Aquí tienes un adelanto.

Una subconsulta encuentra el valor de la tercera fila, y la consulta externa toma todas las películas que no son más largas:

SELECT title, length
FROM film
WHERE length <= (
    SELECT length
    FROM film
    ORDER BY length
    LIMIT 1 OFFSET 2
)
ORDER BY length, title;

Resultado: las mismas 5 películas de 46 minutos que con FETCH FIRST 3 ROWS WITH TIES. Las subconsultas se ven en la lección 6.2.

La función de ventana RANK() da el mismo rango a valores iguales, así que rnk <= 3 conserva todos los empates:

SELECT title, length
FROM (
    SELECT title, length, RANK() OVER (ORDER BY length) AS rnk
    FROM film
) AS ranked
WHERE rnk <= 3
ORDER BY length, title;

Resultado: las mismas 5 películas. RANK() se ve en la lección 7.2.


Sintaxis para limitar filas por base de datos

Base de datosPrimeras N filasOmitir filasWITH TIESPorcentaje
MySQLLIMIT nLIMIT n OFFSET mnono
MariaDB 10.6+LIMIT n, FETCH FIRST n ROWS ONLYLIMIT n OFFSET m, OFFSET m ROWS FETCH NEXT n ROWS ONLYFETCH ... WITH TIESno
PostgreSQL 13+LIMIT n, FETCH FIRST n ROWS ONLYLIMIT n OFFSET m, OFFSET m ROWS FETCH NEXT n ROWS ONLYFETCH ... WITH TIESno
SQL ServerTOP (n)OFFSET m ROWS FETCH NEXT n ROWS ONLYTOP (n) WITH TIESTOP (n) PERCENT
Oracle 12c+FETCH FIRST n ROWS ONLY (ROWNUM antes de 12c)OFFSET m ROWS FETCH NEXT n ROWS ONLYFETCH ... WITH TIESFETCH FIRST n PERCENT ROWS ONLY
FirebirdFIRST n, ROWS n, FETCH FIRST (3.0+)SKIP m, ROWS m TO n, OFFSET ... FETCH (3.0+)nono
SQLiteLIMIT nLIMIT n OFFSET mnono
DuckDBLIMIT n, FETCH FIRST n ROWS ONLYLIMIT n OFFSET m, OFFSET ... FETCHnoLIMIT n%

Si una consulta debe funcionar en varias bases de datos, el estándar OFFSET ... FETCH con ORDER BY cubre la mayoría: todas salvo MySQL y SQLite. Con esta lección terminas los fundamentos de la recuperación de filas; el siguiente módulo muestra cómo transformar valores con funciones SQL.


Conclusiones clave:

  • FETCH FIRST n ROWS ONLY es la alternativa estándar a LIMIT; MySQL y SQLite no la admiten.
  • OFFSET m ROWS FETCH NEXT n ROWS ONLY pagina los resultados; en SQL Server exige ORDER BY.
  • WITH TIES añade las filas que comparten los valores de ordenación de la última fila, así que el resultado puede superar N.
  • SQL Server usa TOP (n), TOP (n) WITH TIES y TOP (n) PERCENT.
  • ROWNUM de Oracle se asigna antes de ORDER BY: ordena primero en una subconsulta o usa FETCH FIRST en 12c+.
  • En MySQL y SQLite, construye WITH TIES con una subconsulta o con RANK().

Preguntas frecuentes

¿Cuál es el equivalente de LIMIT en SQL Server?

Para las primeras filas usa SELECT TOP (n) ...; para paginar, ORDER BY ... OFFSET m ROWS FETCH NEXT n ROWS ONLY. SQL Server no acepta LIMIT ni permite FETCH sin OFFSET.

¿Qué hace WITH TIES en SQL?

Devuelve las primeras N filas más cada fila siguiente con los mismos valores en las columnas de ORDER BY que la fila N. FETCH FIRST 3 ROWS WITH TIES puede devolver 3, 5 o 10 filas, según cuántas compartan el tercer valor.

¿MySQL admite FETCH FIRST o WITH TIES?

No. MySQL 8 y 9 solo admiten LIMIT. MariaDB admite FETCH FIRST ... WITH TIES desde la versión 10.6. En MySQL, obtén el mismo resultado con una subconsulta o con RANK().

¿Cómo limito filas en Oracle?

En Oracle 12c y posteriores usa FETCH FIRST n ROWS ONLY después de ORDER BY. En versiones antiguas ordena en una subconsulta y filtra su resultado con WHERE ROWNUM <= n. Oracle no admite LIMIT.

¿Qué diferencia hay entre FETCH FIRST y FETCH NEXT?

Ninguna: FIRST y NEXT son sinónimos, igual que ROW y ROWS. Por convención, FETCH FIRST se usa sin OFFSET y FETCH NEXT después de él.

Intenta resolver las siguientes tareas para reforzar lo que aprendiste en esta lección.

  1. ¿Cuántas filas devuelve WITH TIES?
  2. Catálogo de productos, página 3
  3. Las 5 primeras filas en SQL Server
  4. Rutas más largas, con empates
  5. Aulas más grandes, con empates