optimizar lentas consultas mysql group-by sql-order-by

mysql - lentas - consultas sql



Seleccione los 3 registros más recientes donde los valores de una columna son distintos (8)

Esto también:

SELECT * FROM OrigTable T INNER JOIN ( SELECT otheridentifier,max(time) AS duration FROM T GROUP BY otheridentifier) S ON S.duration = T.time AND S.otheridentifier = T.otheridentifier.

Tengo la siguiente tabla:

id time text otheridentifier ------------------------------------------- 1 6 apple 4 2 7 orange 4 3 8 banana 3 4 9 pear 3 5 10 grape 2

Lo que quiero hacer es seleccionar los 3 registros más recientes (por tiempo desc), cuyos otheridentifier s son distintos. Entonces, en este caso, el resultado sería id ''s: 5, 4 y 2.

id = 3 se omitirá porque hay un registro más reciente con el mismo campo de otheridentifier .

Esto es lo que traté de hacer:

SELECT * FROM `table` GROUP BY (`otheridentifier`) ORDER BY `time` DESC LIMIT 3

Sin embargo, termino obteniendo filas de id = 5, 3 y 1 en lugar de 5, 4, 2 como se esperaba.

¿Puede alguien decirme por qué esta consulta no me devolvió lo que esperaba? Traté de cambiar el ORDER BY a ASC, pero esto simplemente reorganiza las filas devueltas a 1, 3, 5.


No devuelve lo que esperaba porque la agrupación ocurre antes de ordenar, como se refleja en la posición de las cláusulas en la declaración de SQL. Desgraciadamente, tendrás que ser más elegante para obtener las filas que deseas. Prueba esto:

SELECT * FROM `table` WHERE `id` = ( SELECT `id` FROM `table` as `alt` WHERE `alt`.`otheridentifier` = `table`.`otheridentifier` ORDER BY `time` DESC LIMIT 1 ) ORDER BY `time` DESC LIMIT 3


Puede unirse a la tabla en sí mismo para filtrar la última entrada por otro otheridentifier , y luego tomar las 3 primeras filas de eso:

SELECT last.* FROM `table` last LEFT JOIN `table` prev ON prev.`otheridentifier` = last.`otheridentifier` AND prev.`time` < last.`time` WHERE prev.`id` is null ORDER BY last.`time` DESC LIMIT 3


Puede usar esta consulta para obtener la respuesta correcta:

SELECT * FROM (SELECT * FROM `table` order by time DESC) t group by otheridentifier


Tenía un requisito similar, pero tenía criterios de selección más avanzados. Usando algunas de las otras respuestas, no pude obtener exactamente lo que necesitaba, pero encontré que aún puedes hacer un GROUP BY después y ORDER BY así:

SELECT t.* FROM (SELECT * FROM table ORDER BY time DESC) t GROUP BY t.otheridentifier


qué pasa

SELECT *, max(time) FROM `table` group by otheridentifier


La respuesta de Andomar es probablemente la mejor, ya que no utiliza una subconsulta.

Un enfoque alternativo:

select * from `table` t1 where t1.`time` in ( select max(s2.`time`) from `table` t2 group by t2.otheridentifier )


SELECT * FROM table t1 WHERE t1.time = (SELECT MAX(time) FROM table t2 WHERE t2.otheridentifier = t1.otheridentifier)