1. Qué es
Una tabla no tiene orden. Es un conjunto de filas, y el motor las devuelve como le conviene. Si quieres un orden, tienes que pedirlo.
ORDER BY es el paso 7 del orden-logico-de-ejecucion y LIMIT el 8. De ahí salen las dos ideas del tema:
ORDER BYve el resultado terminado, así que acepta alias y expresiones.LIMITsinORDER BYes una pregunta mal hecha, porque no hay nada que garantice qué filas te toca.
2. Sintaxis
SELECT ...
FROM ...
ORDER BY columna [ASC | DESC] [NULLS FIRST | NULLS LAST], columna2 ...
LIMIT n
OFFSET m;
ASCes el valor por defecto y casi nadie lo escribe.DESCse aplica a una sola columna, no a las que vienen detrás.ORDER BY a, b DESCordenaaascendente ybdescendente.- Se puede ordenar por columna, alias, expresión o número de posición.
OFFSET msalta las primerasmfilas.- La forma del estándar SQL es
OFFSET m ROWS FETCH FIRST n ROWS ONLY. PostgreSQL acepta ambas;LIMITes más corta y es la que se usa.
3. Ejemplos sobre Northwind
Lo básico — los cinco productos más caros:
SELECT product_name, unit_price
FROM products
ORDER BY unit_price DESC
LIMIT 5;
product_name | unit_price
-------------------------+------------
Côte de Blaye | 263.50
Thüringer Rostbratwurst | 123.79
Mishi Kobe Niku | 97.00
Sir Rodney's Marmalade | 81.00
Carnarvon Tigers | 62.50
Dos criterios, y el DESC que solo afecta a uno:
SELECT country, city, company_name
FROM customers
ORDER BY country, city DESC
LIMIT 6;
country | city | company_name
-----------+--------------+----------------------------
Argentina | Buenos Aires | Océano Atlántico Ltda.
Argentina | Buenos Aires | Rancho grande
Argentina | Buenos Aires | Cactus Comidas para llevar
Austria | Salzburg | Piccolo und mehr
Austria | Graz | Ernst Handel
Belgium | Charleroi | Suprêmes délices
País ascendente (Argentina antes que Austria), ciudad descendente dentro de cada país (Salzburg antes que Graz). Para que las dos fueran descendentes habría que escribir ORDER BY country DESC, city DESC.
Y fíjate en las tres empresas de Buenos Aires: su orden entre sí no está definido. Empatan en las dos columnas del ORDER BY, así que el motor las coloca como quiere.
Paginación con OFFSET
SELECT product_name, unit_price FROM products ORDER BY unit_price DESC LIMIT 5; -- página 1
SELECT product_name, unit_price FROM products ORDER BY unit_price DESC OFFSET 5 LIMIT 5; -- página 2
product_name | unit_price
-----------------------+------------
Raclette Courdavault | 55.00
Manjimup Dried Apples | 53.00
Tarte au sucre | 49.30
Ipoh Coffee | 46.00
Rössle Sauerkraut | 45.60
Página n = OFFSET (n-1) * tamaño LIMIT tamaño. Funciona, y tiene dos problemas que conviene saber desde ya:
OFFSETno salta gratis. Para darte las filas 100.001 a 100.010, el motor produce y descarta las 100.000 anteriores. En tablas grandes la paginación se vuelve más lenta cuanto más avanzas.- Si el orden no es determinista, las páginas se solapan o pierden filas. Ver abajo.
El empate: por qué LIMIT necesita desempate
Cuatro productos cuestan exactamente 18.00:
SELECT product_name, unit_price FROM products WHERE unit_price = 18.00;
product_name | unit_price
------------------+------------
Chai | 18.00
Steeleye Stout | 18.00
Chartreuse verte | 18.00
Lakkalikööri | 18.00
Si pides "los 20 productos más caros" y el corte cae en mitad de ese empate, cuál de los cuatro entra no está definido. Puede cambiar al reejecutar, al insertar filas, o al actualizar el motor. Nadie te avisará: cada ejecución devuelve 20 filas y todas parecen bien.
La solución es siempre la misma: añade una columna de desempate única.
SELECT product_name, unit_price
FROM products
ORDER BY unit_price DESC, product_id;
product_id es la clave primaria, así que el orden pasa a ser único y reproducible. Regla práctica: si un ORDER BY va a alimentar una paginación, un informe que se compara entre semanas, o un LIMIT, termínalo con la clave primaria.
Los NULL al ordenar
SELECT company_name, region FROM customers ORDER BY region DESC LIMIT 4;
company_name | region
------------------------------------+--------
Ana Trujillo Emparedados y helados |
Antonio Moreno Taquería |
Around the Horn |
En PostgreSQL el valor por defecto es NULLS LAST en ASC y NULLS FIRST en DESC — los nulos se tratan como si fueran el valor más grande. Se cambia a mano:
ORDER BY region ASC NULLS FIRST
ORDER BY region DESC NULLS LAST
Escríbelo siempre que haya nulos y el orden importe. Es el punto donde PostgreSQL y SQL Server dan resultados distintos con la misma consulta (§ 5).
Ordenar texto: el collation
SELECT city FROM customers ORDER BY city LIMIT 8;
Esta consulta no tiene una única respuesta correcta. Depende de dónde la ejecutes:
en tu PostgreSQL local en Neon
(en_US.UTF-8) (C.UTF-8)
------------------------ --------------
Aachen Aachen
Albuquerque Albuquerque
Anchorage Anchorage
Århus Barcelona
Barcelona Barquisimeto
Barquisimeto Bergamo
Bergamo Berlin
Berlin Bern
En local, Århus sale cuarto: la Å se ordena como una A. En Neon desaparece del top 8, porque allí el orden es por código de byte y la Å se va detrás de la Z.
No es magia ni un error: es el collation de la base, la regla que decide qué texto va antes que cuál. Y no está en la consulta ni en los datos, sino en la configuración de la base:
SELECT datlocprovider, datcollate, datlocale
FROM pg_database WHERE datname = current_database();
Se puede forzar en la propia consulta:
SELECT city FROM customers ORDER BY city COLLATE "C" LIMIT 8;
Si un informe ordenado alfabéticamente sale distinto en dos servidores, el collation es el primer sospechoso. Es un tema con suficiente enjundia como para tener el suyo propio, desarrollado en el vault: temas/sql/collation-y-orden-del-texto.
Ordenar por algo que no está en el SELECT
Es legal y a veces útil:
SELECT product_name FROM products ORDER BY unit_price DESC LIMIT 3;
Devuelve solo los nombres, ordenados por un precio que no se ve. Cómodo, y peligroso en un informe: quien lo lea no puede verificar el orden. Si el criterio importa, enséñalo.
4. Errores comunes
LIMITsinORDER BY. No es "las primeras filas": es "unas filas cualesquiera". Puede cambiar entre ejecuciones.ORDER BYcon empates y sin desempate. El caso de los cuatro productos a 18.00.- Creer que
DESCafecta a todas las columnas. Afecta solo a la suya. - Ordenar por número de posición en código que se guarda.
ORDER BY 2es cómodo para probar; el día que alguien añade una columna alSELECT, el orden cambia solo y en silencio. - Esperar que
LIMIT 10haga rápida una consulta lenta. Es el último paso: antes ya se ordenó todo. Ver orden-logico-de-ejecucion § 5. - Paginar con
OFFSETsobre un orden no determinista. La fila 10 de la página 1 puede repetirse como fila 1 de la página 2. - Ordenar un número guardado como texto.
'10' < '9'es cierto en texto. Si una columna de importes está envarchar, el orden será alfabético y parecerá aleatorio.
5. Diferencias con SQL Server
| PostgreSQL | SQL Server | |
|---|---|---|
| Limitar | LIMIT 5 |
TOP 5 (dentro del SELECT) |
| Saltar y limitar | OFFSET 5 LIMIT 5 |
ORDER BY ... OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY |
Nulos en ASC |
Al final | Al principio |
NULLS FIRST/LAST |
Sí | ❌ No existe; se emula con ORDER BY CASE WHEN col IS NULL THEN 1 ELSE 0 END, col |
| Sensibilidad del orden | Collation de la base o de la columna | Collation, y por defecto suele ser insensible a mayúsculas |
La fila de los nulos es la que rompe migraciones. La misma consulta, los mismos datos, y las filas sin región salen arriba en un motor y abajo en el otro. Si alguien compara los dos informes fila a fila, no cuadran — y la causa no está a la vista en la consulta.
Detalle de entrevista: en SQL Server, TOP sin ORDER BY no garantiza nada, exactamente igual que LIMIT. Es la misma trampa con otro nombre.
6. Ejercicios
- Los 10 pedidos con mayor flete, del más caro al más barato, mostrando id, cliente y flete.
- Clientes ordenados por país y, dentro de cada país, por ciudad — ambos ascendentes — y con los que no tienen región primero.
- Los productos ordenados de más caro a más barato, garantizando que dos ejecuciones dan exactamente el mismo orden.
- La segunda página de empleados, con páginas de 3, ordenados por apellido.
- Sin ejecutarla, di qué problema tiene:
sql SELECT customer_id, order_date FROM orders ORDER BY order_date DESC LIMIT 10;
7. Pregunta de negocio
Dirección quiere "el top 10 de productos más caros" para una presentación, y lo va a repetir cada trimestre para comparar. ¿Qué consulta entregas y qué le adviertes?