ORDER BY y LIMIT en SQL
En esta lección
Una tienda online muestra los productos del más barato al más caro, un instituto lista a los alumnos por apellido y un ranking enseña los diez mejores. Todo eso se consigue con dos piezas: ORDER BY, que ordena el resultado, y LIMIT, que se queda solo con unas cuantas filas. En esta lección verás cómo ordenar por una o varias columnas, por alias y por cálculos, dónde acaban los NULL, cómo paginar resultados y cómo sacar el “top N” de cualquier cosa.
Ordenar: ORDER BY
Sin ORDER BY, la base de datos devuelve las filas en el orden que le convenga, que no tiene por qué ser el de inserción ni ser siempre el mismo. Suele parecer ordenado por id, pero es casualidad: después de borrar filas, crear un índice o cambiar de versión, el orden puede cambiar. Si el orden te importa, indícalo:
SELECT nombre, edad
FROM clientes
ORDER BY edad;
| nombre | edad |
|---|---|
| Pablo Díaz | 17 |
| Luis Pérez | 22 |
| Eva Martín | 29 |
| Ana García | 34 |
| Marta Ruiz | 45 |
ASC y DESC
ASC(ascending): de menor a mayor. Es el valor por defecto, así que no hace falta escribirlo.DESC(descending): de mayor a menor.
SELECT id, importe
FROM pedidos
ORDER BY importe DESC;
| id | importe |
|---|---|
| 2 | 120.50 |
| 4 | 60.00 |
| 1 | 45.00 |
| 5 | 33.25 |
| 3 | 12.99 |
Qué significa “menor” depende del tipo de la columna:
| Tipo | ASC ordena… | Ejemplo |
|---|---|---|
| Números | De menor a mayor | 12.99, 33.25, 45.00 |
| Textos | Alfabéticamente, de la A a la Z | Ana, Eva, Luis |
| Fechas | De la más antigua a la más reciente | 2026-09-01, 2026-09-03 |
Así, los pedidos más recientes primero se piden con ORDER BY fecha DESC:
SELECT id, fecha
FROM pedidos
ORDER BY fecha DESC;
| id | fecha |
|---|---|
| 5 | 2026-09-15 |
| 4 | 2026-09-12 |
| 3 | 2026-09-10 |
| 2 | 2026-09-03 |
| 1 | 2026-09-01 |
Nota: cómo se ordenan los textos (si “a” va junto a “A”, dónde va la “ñ” o las letras con tilde) lo decide la intercalación (collation) de la columna. Cada sistema tiene la suya por defecto; lo verás en CREATE TABLE.
Ordenar por varias columnas
Si dos filas empatan en la primera columna, se desempata con la segunda, y así sucesivamente. Cada columna lleva su propio ASC o DESC:
SELECT nombre, ciudad, edad
FROM clientes
ORDER BY ciudad, edad DESC;
| nombre | ciudad | edad |
|---|---|---|
| Luis Pérez | Bilbao | 22 |
| Eva Martín | Madrid | 29 |
| Pablo Díaz | Madrid | 17 |
| Marta Ruiz | Santander | 45 |
| Ana García | Santander | 34 |
Ordena por ciudad de la A a la Z y, dentro de cada ciudad, por edad de mayor a menor.
Cuidado: el
DESCsolo afecta a la columna que tiene delante.ORDER BY ciudad, edad DESCordena la ciudad en ascendente. Si quieres las dos al revés, escribeORDER BY ciudad DESC, edad DESC.
¿Y si hay empate y no das una segunda columna? Con ORDER BY ciudad, Pablo y Eva (los dos de Madrid) pueden salir en cualquier orden, y ese orden puede cambiar de una ejecución a otra. Cuando necesites un orden estable, por ejemplo para paginar, añade al final una columna única como el id: ORDER BY ciudad, id.
Ordenar por alias y por expresiones
ORDER BY se ejecuta después del SELECT (recuerda el orden lógico de la lección de SELECT), así que puede usar los alias que hayas definido:
SELECT id, importe, ROUND(importe * 1.21, 2) AS con_iva
FROM pedidos
ORDER BY con_iva DESC;
| id | importe | con_iva |
|---|---|---|
| 2 | 120.50 | 145.81 |
| 4 | 60.00 | 72.60 |
| 1 | 45.00 | 54.45 |
| 5 | 33.25 | 40.23 |
| 3 | 12.99 | 15.72 |
También puedes ordenar por un cálculo que ni siquiera aparece en el resultado. Por ejemplo, los clientes cuya edad está más cerca de 30 años (ABS es el valor absoluto, lo verás en funciones):
SELECT nombre, edad
FROM clientes
ORDER BY ABS(edad - 30);
| nombre | edad |
|---|---|
| Eva Martín | 29 |
| Ana García | 34 |
| Luis Pérez | 22 |
| Pablo Díaz | 17 |
| Marta Ruiz | 45 |
Eva está a 1 año de distancia, Ana a 4, Luis a 8, Pablo a 13 y Marta a 15. Y puedes ordenar por una columna que no está en el SELECT: SELECT nombre FROM clientes ORDER BY edad es perfectamente válido.
Ordenar por número de columna
También existe ORDER BY 2, 1, que significa “por la segunda columna del SELECT y luego por la primera”:
SELECT nombre, ciudad
FROM clientes
ORDER BY 2, 1; -- por ciudad y luego por nombre
Funciona en todos los sistemas, pero evítalo en código que vaya a durar: si alguien añade una columna al principio del SELECT, el orden cambia sin que nadie se dé cuenta. Úsalo solo en consultas rápidas a mano.
Los NULL al ordenar
¿Dónde acaban las filas sin valor? Depende del sistema: MySQL, MariaDB y SQLite ponen los NULL al principio en orden ascendente (se consideran menores que cualquier valor), mientras que PostgreSQL y Oracle los ponen al final. Con DESC, al revés.
Para controlarlo:
-- PostgreSQL y SQLite (desde 3.30): los NULL al final
SELECT nombre, nota FROM alumnos ORDER BY nota NULLS LAST;
-- MySQL: primero las filas con nota (nota IS NULL vale 0) y luego las que no (vale 1)
SELECT nombre, nota FROM alumnos ORDER BY nota IS NULL, nota;
Lo explicamos con ejemplos en valores NULL.
Limitar el número de filas: LIMIT
LIMIT n devuelve como mucho n filas. Casi siempre va con ORDER BY, porque sin orden no sabes cuáles te llegan.
-- Los 3 pedidos más altos
SELECT id, importe
FROM pedidos
ORDER BY importe DESC
LIMIT 3;
| id | importe |
|---|---|
| 2 | 120.50 |
| 4 | 60.00 |
| 1 | 45.00 |
ORDER BY + LIMIT es la receta para cualquier top N: los más vendidos, los últimos registrados, las mejores notas. Los dos últimos pedidos:
SELECT id, fecha, importe
FROM pedidos
ORDER BY fecha DESC
LIMIT 2;
| id | fecha | importe |
|---|---|---|
| 5 | 2026-09-15 | 33.25 |
| 4 | 2026-09-12 | 60.00 |
Y con LIMIT 1 obtienes “el que más” o “el que menos”. El cliente mayor de edad de más edad:
SELECT nombre, edad
FROM clientes
WHERE edad >= 18
ORDER BY edad DESC
LIMIT 1;
| nombre | edad |
|---|---|
| Marta Ruiz | 45 |
Cuidado con los empates: si dos pedidos tuvieran el mismo importe máximo,
LIMIT 1devolvería solo uno de ellos, y cualquiera. Si necesitas todos los empatados, usa una subconsulta:WHERE importe = (SELECT MAX(importe) FROM pedidos).
Saltar filas: OFFSET y la paginación
Cuando una tienda tiene 500 productos, no los enseña todos a la vez: los reparte en páginas. OFFSET indica cuántas filas saltar antes de empezar a devolver:
-- Página 2, con 2 resultados por página
SELECT nombre
FROM clientes
ORDER BY nombre
LIMIT 2 OFFSET 2;
| nombre |
|---|
| Luis Pérez |
| Marta Ruiz |
OFFSET 2 salta Ana y Eva (la página 1) y LIMIT 2 devuelve las 2 siguientes. La fórmula para cualquier página es:
OFFSET = (número de página - 1) × resultados por página
| Página | Consulta | Resultado |
|---|---|---|
| 1 | LIMIT 2 OFFSET 0 | Ana García, Eva Martín |
| 2 | LIMIT 2 OFFSET 2 | Luis Pérez, Marta Ruiz |
| 3 | LIMIT 2 OFFSET 4 | Pablo Díaz |
La última página puede tener menos filas, y una página que no existe devuelve un resultado vacío, sin error.
Nota: MySQL también acepta la forma corta
LIMIT 2, 2, donde el primer número es el desplazamiento y el segundo la cantidad. Es fácil confundirse, así que es mejor escribirLIMIT ... OFFSET ..., que además funciona en PostgreSQL y SQLite.
Para paginar bien, el ORDER BY debe dar un orden único. Si hay empates, una fila podría salir en dos páginas o en ninguna. Añade el id como último criterio.
Consejo: con tablas enormes,
OFFSET 100000es lento, porque la base de datos tiene que recorrer y descartar esas 100 000 filas. Las aplicaciones grandes usan otra técnica: recordar el últimoidvisto y pedirWHERE id > ultimo_id ORDER BY id LIMIT 20.
LIMIT en otros sistemas
LIMIT funciona en MySQL, MariaDB, PostgreSQL y SQLite, pero no es SQL estándar. Estas son las equivalencias:
| Sistema | Los 3 primeros | Saltando 2 |
|---|---|---|
| MySQL, MariaDB, PostgreSQL, SQLite | LIMIT 3 | LIMIT 3 OFFSET 2 |
| Estándar SQL (PostgreSQL, Oracle) | FETCH FIRST 3 ROWS ONLY | OFFSET 2 ROWS FETCH NEXT 3 ROWS ONLY |
| SQL Server | SELECT TOP 3 ... | OFFSET 2 ROWS FETCH NEXT 3 ROWS ONLY |
Por ejemplo, en SQL Server:
SELECT TOP 3 id, importe
FROM pedidos
ORDER BY importe DESC;
Y en la forma estándar (PostgreSQL u Oracle; MySQL no la admite):
SELECT id, importe
FROM pedidos
ORDER BY importe DESC
FETCH FIRST 3 ROWS ONLY;
El lugar de cada parte
ORDER BY va después de WHERE (y de GROUP BY y HAVING, si los hay), y LIMIT va al final del todo. Es también el orden en que se ejecutan: primero se filtra, luego se ordena lo que queda y por último se recortan las filas. Poner LIMIT antes de ORDER BY da un error de sintaxis.
Errores frecuentes
- Confiar en el orden “natural”: sin
ORDER BY, el orden no está garantizado. - Usar
LIMITsinORDER BY: obtienes “unas” filas, no “las primeras”. - Creer que
DESCafecta a todas las columnas: solo a la que tiene delante. - Paginar con un orden que tiene empates: filas repetidas o perdidas entre páginas.
- Confundir
LIMIT 5, 10de MySQL: salta 5 y devuelve 10, no “de la 5 a la 10”. - Escribir
ORDER BYantes deWHERE: error de sintaxis.
Resumen
| Quieres… | Escribe |
|---|---|
| Ordenar de menor a mayor | ORDER BY edad (o ASC) |
| De mayor a menor | ORDER BY importe DESC |
| Por varias columnas | ORDER BY ciudad, edad DESC |
| Por un alias o un cálculo | ORDER BY con_iva, ORDER BY ABS(edad - 30) |
Los NULL al final | NULLS LAST (PostgreSQL/SQLite), ORDER BY col IS NULL, col (MySQL) |
| Los N primeros | ORDER BY ... LIMIT N |
| Una página | LIMIT tamanio OFFSET (pagina - 1) * tamanio |
| Estándar / SQL Server | FETCH FIRST N ROWS ONLY / TOP N |
En la siguiente lección conocerás las funciones de texto, números y fechas.
Pon a prueba lo que has aprendido
¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.