¿Cómo procesa MySQL ORDER BY y LIMIT en una consulta?


251

Tengo una consulta que se ve así:

SELECT article FROM table1 ORDER BY publish_date LIMIT 20

¿Cómo funciona ORDER BY? ¿Ordenará todos los registros, luego obtendrá los primeros 20, o obtendrá 20 registros y los ordenará por publish_datecampo?

Si es el último, no se garantiza que realmente obtenga los 20 artículos más recientes.


66
Tenga en cuenta que si algunos publish_dates son iguales, ordenar por ellos no da resultados determinados, lo que significa que si los usa LIMITpara paginar, ¡puede terminar obteniendo los mismos artículos en diferentes páginas!
Konrad Morawski el

Respuestas:


245

Primero ordenará, luego obtendrá los primeros 20. Una base de datos también procesará cualquier cosa en la WHEREcláusula anterior ORDER BY.


1
¿Entonces el tiempo es igual?
Yasar Arafath

77
¡Incorrecto! LIMITse rompe ORDER BY. Con LIMITun ORDER BYresultado incorrecto devuelve. LIMITde alguna manera reordena el conjunto de resultados devuelto porORDER BY
Green

66
@ Green, te equivocas. Lea esto para la explicación: dev.mysql.com/doc/refman/5.7/en/limit-optimization.html Cuando se indexa la columna ORDER BY, puede devolver registros en un orden diferente que sin el LIMIT, cuando hay más de 1 registros con el mismo valor en esa columna.
yitwail

1
Una solución rápida para tales problemas es agregar una columna más al orden preferiblemente teniendo valores únicos para que la base de datos obtenga una regla consistente para ordenar filas cuando el valor del primer orden por columna es el mismo para varias filas.
rineez

37

La cláusula LIMIT puede usarse para restringir el número de filas devueltas por la instrucción SELECT. LIMIT toma uno o dos argumentos numéricos, que deben ser constantes enteras no negativas (excepto cuando se usan declaraciones preparadas).

Con dos argumentos, el primer argumento especifica el desplazamiento de la primera fila para devolver, y el segundo especifica el número máximo de filas para devolver. El desplazamiento de la fila inicial es 0 (no 1):

SELECT * FROM tbl LIMIT 5,10; # Retrieve rows 6-15

Para recuperar todas las filas desde un cierto desplazamiento hasta el final del conjunto de resultados, puede usar un número grande para el segundo parámetro. Esta declaración recupera todas las filas desde la fila 96 hasta la última:

SELECT * FROM tbl LIMIT 95,18446744073709551615;

Con un argumento, el valor especifica el número de filas a devolver desde el comienzo del conjunto de resultados:

SELECT * FROM tbl LIMIT 5; # Retrieve first 5 rows

En otras palabras, LIMIT row_count es equivalente a LIMIT 0, row_count.

Todos los detalles en: http://dev.mysql.com/doc/refman/5.0/en/select.html


¿No se recuperan las filas 5-14?
Adonis K. Kakoulidis

@adonis No, no lo es. El ejemplo es el correcto de la documentación de MySQL
dcaswell

El número 5 es la sexta fila. Se ignoran 5 filas (de 0 a 4).
Phil Perry

1
¡Pero usar LIMIT sin ORDER BY puede dar resultados inconsistentes! Desafortunadamente, todo el conjunto de resultados debe pedirse antes de que se aplique el LÍMITE o el DBMS es libre de ordenar arbitrariamente el resultado y luego DESPLAZAR y LIMITAR en ese conjunto. He leído que esto puede deberse a que el DBMS seleccionó un Plan de consulta alternativo basado en OFFSET y LIMIT, por lo tanto, el orden arbitrario.
Barton

44
pregunta es pedir el límite y ordenar por. Pero la respuesta no está relacionada con esta pregunta en absoluto
Shen liang el

9

Tal como dice @James, ordenará todos los registros y luego obtendrá las primeras 20 filas.

Como es así, tiene la garantía de obtener los 20 primeros artículos publicados, los más nuevos no se mostrarán.

En su situación, recomiendo que se agrega desca order by publish_date, si desea que los artículos más nuevos, a continuación, el artículo más reciente será la primera.

Si necesita mantener el resultado en orden ascendente, y todavía quiere los 10 artículos más recientes, puede pedirle a mysql que clasifique su resultado dos veces.

Esta consulta a continuación ordenará el resultado descendente y limitará el resultado a 10 (esa es la consulta dentro del paréntesis). Todavía se ordenará en orden descendente, y no estamos satisfechos con eso, por lo que le pedimos a mysql que lo ordene una vez más. Ahora tenemos el resultado más nuevo en la última fila.

select t.article 
from 
    (select article, publish_date 
     from table1
     order by publish_date desc limit 10) t 

order by t.publish_date asc;

Si necesita todas las columnas, se hace de esta manera:

select t.* 
from 
    (select * 
     from table1  
     order by publish_date desc limit 10) t 

order by t.publish_date asc;

Utilizo esta técnica cuando escribo consultas manualmente para examinar la base de datos en busca de varias cosas. No lo he usado en un entorno de producción, pero ahora cuando lo marqué en el banco, la clasificación adicional no afecta el rendimiento.


2
Su clasificación adicional prácticamente no puede tener ningún impacto medible en el rendimiento, ya que se limita a 10 filas / elementos solamente :-). En general, la ordenación de una tabla en memoria (que está produciendo una sub-selección) es muy rápida y apenas medible a menos que tenga millones de filas o el DBMS esté paginando el conjunto de resultados en el disco, ya que no cabe en la memoria (en cuyo caso dependiendo del DBMS también puede abortar la consulta).
Martin Kersten

7

Si hay un índice adecuado, en este caso en el publish_datecampo, entonces MySQL no necesita escanear todo el índice para obtener los 20 registros solicitados; los 20 registros se encontrarán al comienzo del índice. Pero si no hay un índice adecuado, se necesitará un análisis completo de la tabla.

Hay un artículo de MySQL Performance Blog de 2009 sobre esto.


7

Puede agregar [asc] o [desc] al final del pedido para obtener los registros más antiguos o más recientes

Por ejemplo, esto le dará primero los últimos registros

ORDER BY stamp DESC

Añadir la LIMITcláusula despuésORDER BY


3
Bienvenido a stackoverflow. Creo que puede haber entendido mal la pregunta. Creo que estaban preguntando sobre el orden de las operaciones en lugar de "cómo ordenar". (Pero es discutible ya que la pregunta ya fue respondida hace un tiempo;)
Leigh

5

Puede usar este código SELECT article FROM table1 ORDER BY publish_date LIMIT 0,10 donde 0 es un límite de inicio de registro y 10 número de registro


8
No, eso no es obligatorio . LIMIT 10es la abreviatura LIMIT 0,10.
Lawrence Dol

2
sí, no se requiere para el LÍMITE 0,10, pero se puede requerir como este Límite 10,20
gaurangkathiriya

3

LÍMITE generalmente se aplica como la última operación, por lo que el resultado primero se ordenará y luego se limitará a 20. De hecho, la clasificación se detendrá tan pronto como se encuentren los primeros 20 resultados ordenados.


11
Tu segunda oración va en contra de la primera. La clasificación no puede detenerse cuando se encuentran los primeros 20 resultados porque, como dijiste, la clasificación se realizará antes de que se devuelvan los resultados. MySQL solo puede saber cuáles son los primeros 20 resultados después de que la clasificación haya finalizado.
Tom

@ Tom, en realidad puede, si lo ordena por una columna indexada. Se explica aquí: dev.mysql.com/doc/refman/5.7/en/limit-optimization.html
yitwail

-3

Además, la sintaxis de LIMIT es diferente según las bases de datos, por ejemplo:

mysql - LÍMITE 1, 2

postgres - LIMIT 2 OFFSET 1

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.