La idea
Una tabla es un montón de filas, no una lista. No hay primera fila ni última. El orden que ves al
ejecutar SELECT * FROM products es el que a la base de datos le resultó cómodo, y puede cambiar tras
una actualización, con otro plan de ejecución o en otra máquina.
El orden solo existe cuando lo pides con ORDER BY. Y LIMIT no tiene idea de orden por sí solo: toma
"las primeras N filas" del orden que exista en ese momento. Así que todo "top 10", "las últimas 5" o
"página 2" son en realidad dos pasos: ordenar y luego cortar. Si el orden no está del todo definido, el
corte tampoco.
Figura 1
Ordenar y luego cortar: si hay empates en el corte, la respuesta es una moneda al aire
| product_id | name | unit_price |
|---|---|---|
| 141 | Thatcher Acacia Dutch Oven | 13.99 |
| 152 | Monroe Stoneware Utensil Set | 13.99 |
| 170 | Rowan Cashmere-Blend Throw Blanket | 17.99 |
| 172 | Maple Wool Throw Pillow | 18.99 |
| 182 | Nantucket Brass Wall Mirror | 17.99 |
| 184 | Thatcher Oak Candle | 17.99 |
| product_id | name | unit_price |
|---|---|---|
| 141 | Thatcher Acacia Dutch Oven | 13.99 |
| 152 | Monroe Stoneware Utensil Set | 13.99 |
| 170 | Rowan Cashmere-Blend Throw Blanket | 17.99 |
| 182 | Nantucket Brass Wall Mirror | 17.99 |
| 184 | Thatcher Oak Candle | 17.99 |
| 172 | Maple Wool Throw Pillow | 18.99 |
- Seis productos tal como están guardados. Su posición en la tabla no significa nada: la base de datos no promete ningún orden a menos que lo pidas.
ORDER BY unit_pricepone primero el más barato. Tres productos cuestan exactamente 17.99, y para ellos el precio solo no dice quién va primero.- Agrega un desempate,
ORDER BY unit_price, product_id. Dentro de cada grupo de precios iguales va primero el id menor, así que el orden es el mismo siempre. LIMIT 4conserva las cuatro primeras filas. El corte cae dentro del grupo de 17.99. Sin el desempate, el producto 184 podría quedarse con el cuarto lugar en vez del 182.
Por qué existe
"Top 10 de productos", "los 5 pedidos más recientes" y "página 2 de la lista de precios" son la mitad de las solicitudes que reciben los analistas. Tienen que ser repetibles. Si la página principal muestra una lista de más vendidos distinta en cada recarga por culpa de los empates, alguien lo nota. Las bases de datos guardan las filas en la disposición más rápida de escribir, y por eso el orden queda sin definir a menos que digas otra cosa.
LIMIT existe porque un resultado de 12,000 filas casi nunca es lo que necesitas. Enviar tres filas en
vez de doce mil es más rápido, más fácil de revisar y más fácil de mostrar.
Hay una segunda razón para cuidarlo. Una lista ordenada es una promesa que le haces al lector. Cuando un panel dice "top 10", la gente actúa: repone inventario, aplica descuentos o escribe sobre esos productos. Una lista que depende en silencio de la suerte es una lista que no puedes defender cuando alguien pregunta por qué hoy falta el producto 184.
Cómo funciona por dentro
Ordenar y cortar ocurren al final de la consulta, después de filtrar, agrupar y construir las filas:
- La base de datos termina
FROM,WHERE,GROUP BYySELECT, y obtiene un conjunto de filas de salida. ORDER BYlas organiza por la primera columna. Cuando dos filas tienen valores iguales, mira la segunda columna, luego la tercera, y así sucesivamente.OFFSETsalta esa cantidad de filas desde arriba.LIMITconserva las N filas siguientes y descarta el resto.
Como ORDER BY corre después de SELECT, puede usar tus alias e incluso la posición de una columna de
salida (ORDER BY 2). La posición es frágil: agrega una columna al SELECT y el orden cambia. Prefiere
los nombres.
Empates y desempate
Siempre que la columna de orden pueda repetirse, las filas con valores iguales quedan en un orden
indefinido entre sí. En una lista larga eso no hace daño. Importa en cuanto LIMIT corta por en medio
del empate. La solución es una columna más que sea única, normalmente el id: ORDER BY unit_price, product_id. No cuesta nada y convierte una respuesta arbitraria en una estable. Trátalo como parte de
todo top N. Los niveles repiten el hábito hasta que se vuelve automático.
Paginación
Una página es una ventana sobre una lista ordenada. La página p de tamaño n es
LIMIT n OFFSET (p - 1) * n.
Figura 2
OFFSET salta filas, LIMIT toma filas: eso es una página
| product_id | name | unit_price |
|---|---|---|
| 141 | Thatcher Acacia Dutch Oven | 13.99 |
| 152 | Monroe Stoneware Utensil Set | 13.99 |
| 170 | Rowan Cashmere-Blend Throw Blanket | 17.99 |
| 182 | Nantucket Brass Wall Mirror | 17.99 |
| 184 | Thatcher Oak Candle | 17.99 |
| 172 | Maple Wool Throw Pillow | 18.99 |
- Páginas de dos. La página 1 es
LIMIT 2 OFFSET 0: no saltes nada, toma dos. - La página 2 es
LIMIT 2 OFFSET 2: salta las dos primeras filas y toma las dos siguientes. - La página 3 es
LIMIT 2 OFFSET 4. El offset siempre es (página - 1) por el tamaño de página. Esto solo funciona porque el orden es el mismo en cada petición.
La paginación solo funciona con un orden determinista. Si los empates pueden reacomodarse entre
peticiones, una fila puede aparecer en la página 2 y otra vez en la 3, o nunca. También tiene un costo:
para llegar a OFFSET 10000 la base de datos igual ordena y recorre 10,000 filas. Está bien para un
directorio de empleados y es mala idea para recorrer millones de eventos.
Qué significa "menor" para texto y fechas
Los números se ordenan por valor, las fechas por tiempo y el texto por alfabeto. Una columna de texto con
números se ordena como texto, así que '100' va antes que '20' porque se compara primero el primer
carácter. Los timestamps se ordenan bien porque el formato pone primero la unidad más grande, por eso
ORDER BY order_date DESC LIMIT 5 de verdad da los cinco pedidos más recientes. Si un orden se ve
desordenado, revisa primero el tipo de la columna.
Revisar un top N
Dos pruebas rápidas atrapan casi todos los errores. Primera: ejecuta la consulta sin LIMIT y mira dónde
cae el corte; si las filas justo encima y debajo comparten el valor de orden, tienes un empate y
necesitas un desempate. Segunda: cambia DESC por ASC y comprueba si el otro extremo de la lista tiene
sentido. Un "top 10 de reembolsos" que empieza con un número negativo o un NULL tiene un problema de
datos, no de SQL.
Dirección y NULL
ASC es el valor por defecto y DESC lo invierte. Cada columna de la lista tiene su propia dirección:
ORDER BY category, unit_price DESC agrupa por categoría y muestra primero el producto más caro dentro
de cada una. Los NULL necesitan una decisión, porque no son ni pequeños ni grandes. Distintas bases de
datos los ponen al principio o al final con la misma consulta, así que cuando importe, dilo con
NULLS FIRST o NULLS LAST en lugar de confiar en el valor por defecto.
Errores comunes
"La tabla ya está en orden, no necesito ORDER BY"
Parece ordenada porque las filas se cargaron en orden de id y todavía nada ha cambiado. Agrega un índice,
actualiza una fila o mueve los datos a otro servidor y puede cambiar. Si tu resultado depende del orden,
escribe ORDER BY, siempre.
"ORDER BY más LIMIT siempre da las mismas filas"
Solo si el orden está completamente determinado. Con empates en el corte, dos ejecuciones pueden
devolver filas distintas, y las dos son correctas para SQL. Agrega al final del ORDER BY una columna
única y la respuesta será la misma cada vez.
"DESC significa que los valores más grandes van primero, NULL incluidos"
Los NULL no siguen tu intuición. En algunas bases de datos se ordenan como el valor más grande y salen
primero en una lista DESC, en otras salen al final. Una lista de "más caros primero" puede empezar con
productos sin precio. Fíltralos o colócalos de forma explícita con NULLS LAST.
Ponte a prueba
Una pregunta. Al responderla, la lección queda marcada en el mapa; nunca bloquea un nivel.
No del todo. ORDER BY solo garantiza el orden de la columna por la que ordenaste. Los precios iguales pueden salir en cualquier orden, y el corte cae entre ellos.Prueba otra respuesta.
No del todo. La consulta se ejecuta sin ningún aviso, y ese es el problema. Simplemente devuelve una elección arbitraria entre las filas empatadas.Prueba otra respuesta.
Correcto. Los precios iguales empatan, la base de datos puede devolverlos en cualquier orden, y el corte parte el grupo. Agregar , product_id fija la elección.
No del todo. Los empates nunca se eliminan. Todas las filas se ordenan y LIMIT toma las cuatro primeras, caigan donde caigan.Prueba otra respuesta.
Lección hecha: ya está marcada en el mapa.