SQL · Capítulo 3 · Lección de conceptos · 6 min de lectura

Por qué una tabla no tiene orden hasta que lo pides

Una tabla es un conjunto de filas sin primera ni última. El orden solo existe cuando lo pides, y LIMIT es tan confiable como el orden que tiene debajo.

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

products
product_idnameunit_price
141Thatcher Acacia Dutch Oven13.99
152Monroe Stoneware Utensil Set13.99
170Rowan Cashmere-Blend Throw Blanket17.99
172Maple Wool Throw Pillow18.99
182Nantucket Brass Wall Mirror17.99
184Thatcher Oak Candle17.99
ORDER BY unit_price, product_id
product_idnameunit_price
141Thatcher Acacia Dutch Oven13.99
152Monroe Stoneware Utensil Set13.99
170Rowan Cashmere-Blend Throw Blanket17.99
182Nantucket Brass Wall Mirror17.99
184Thatcher Oak Candle17.99
172Maple Wool Throw Pillow18.99

Paso 1 de 4 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.

  1. 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.
  2. ORDER BY unit_price pone primero el más barato. Tres productos cuestan exactamente 17.99, y para ellos el precio solo no dice quién va primero.
  3. 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.
  4. LIMIT 4 conserva 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:

  1. La base de datos termina FROM, WHERE, GROUP BY y SELECT, y obtiene un conjunto de filas de salida.
  2. ORDER BY las organiza por la primera columna. Cuando dos filas tienen valores iguales, mira la segunda columna, luego la tercera, y así sucesivamente.
  3. OFFSET salta esa cantidad de filas desde arriba.
  4. LIMIT conserva 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

La misma lista ordenada
product_idnameunit_price
141Thatcher Acacia Dutch Oven13.99
152Monroe Stoneware Utensil Set13.99
170Rowan Cashmere-Blend Throw Blanket17.99
182Nantucket Brass Wall Mirror17.99
184Thatcher Oak Candle17.99
172Maple Wool Throw Pillow18.99

Paso 1 de 3 Páginas de dos. La página 1 es LIMIT 2 OFFSET 0: no saltes nada, toma dos.

  1. Páginas de dos. La página 1 es LIMIT 2 OFFSET 0: no saltes nada, toma dos.
  2. La página 2 es LIMIT 2 OFFSET 2: salta las dos primeras filas y toma las dos siguientes.
  3. 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.

Quieres los 4 productos más baratos, ejecutas ORDER BY unit_price LIMIT 4 y obtienes 141, 152, 170, 182. Los precios de 170, 182 y 184 son todos 17.99. Un colega ejecuta la misma consulta mañana. ¿Qué puede pasar?

Elige qué puede ejecutarse en este sitio. Puedes cambiarlo cuando quieras desde "Configurar cookies", al pie de cada página.