2012-02-08 25 views
14

¿Hay alguna manera más eficiente de hacer lo siguiente?Devolviendo la 'última' fila de cada 'grupo por' en MySQL

select * 
    from foo as a 
    where a.id = (select max(id) from foo where uid = a.uid group by uid) 
    group by uid; 
) 

Esta respuesta parece similar, pero esta respuesta es la mejor forma de hacer esto - How to select the first row for each group in MySQL?

Gracias,

Chris.

P.S. la mesa se ve así:

CREATE TABLE foo (
    id INT(10) NOT NULL AUTO_INCREMENT, 
    uid INT(10) NOT NULL, 
    value VARCHAR(50) NOT NULL, 
    PRIMARY KEY (`id`), 
    INDEX `uid` (`uid`) 
) 

de datos:

id, uid, value 
1, 1, hello 
2, 2, cheese 
3, 2, pickle 
4, 1, world 

resultados:

id, uid, value 
3, 2, pickle 
4, 1, world 

Ver http://www.barricane.com/2012/02/08/mysql-select-last-matching-row.html para más detalles.

+0

Esta es una subconsulta correlacionada. En general, una subconsulta no correlacionada será más rápida, según el ejemplo de Devart. – Strawberry

+0

posible duplicado de [Recuperando el último registro en cada grupo] (http: // stackoverflow.com/questions/1313120/retrieving-the-last-record-in-each-group) –

Respuesta

33

Intentar esta consulta -

SELECT t1.* FROM foo t1 
    JOIN (SELECT uid, MAX(id) id FROM foo GROUP BY uid) t2 
    ON t1.id = t2.id AND t1.uid = t2.uid; 

A continuación, utilice EXPLAIN para analizar consultas.


SELECT t1.* FROM foo t1 
    LEFT JOIN foo t2 
    ON t1.id < t2.id AND t1.uid = t2.uid 
WHERE t2.id is NULL; 
+0

Esto no funciona como una vista: obtengo "ERROR 1349 (HY000): el SELECCIONAR de View contiene una subconsulta en la cláusula FROM", mientras que mi código sí. – fadedbee

+1

No sabía que lo iba a usar para ver. ... He agregado otro. – Devart

+0

Gracias, tendré que hacer algunas pruebas en las tres alternativas e informaré. (Pude hacer que tu primera solución funcionara para las vistas haciendo que la subconsulta fuera una vista separada.) – fadedbee

2

si la tabla es grande en tamaño. Hacer view que contiene toda la última fila Identificación

create view lastrecords as (select max(id) from foo where uid = a.uid group by uid) 

Ahora se añaden a la consulta principal con este view. Será más rápido.

SELECT t1.* FROM tablename as t1 
    JOIN lastrecords as t2 
    ON t1.id = t2.id AND t1.uid = t2.uid; 

o puede hacerlo unirse con los últimos registros directos de consulta también:

SELECT t1.* FROM tablename as t1 
JOIN (SELECT uid, MAX(id) id FROM tablename GROUP BY id) as t2 
ON t1.id = t2.id AND t1.uid = t2.uid; 
0

Esto ha funcionado para mí, gracias!

SELECT t1.* FROM foo t1 
    JOIN (SELECT uid, MAX(id) id FROM foo GROUP BY uid) t2 
    ON t1.id = t2.id AND t1.uid = t2.uid; 

mi versión:

SELECT * FROM messages t1 JOIN (SELECT MAX(id) id FROM messages where uid = 8279 and actv=1 GROUP BY uid) t2 ON t1.id = t2.id ORDER BY datex desc LIMIT 0,10; 

este código de abajo no devuelve todas las filas que quiero porque si la columna max id es un inactivo entonces se salta el grupo incluso si el grupo tiene filas activas. .

select * from messages where uid = 8279 and actv=1 and id In (Select max(id) From messages Group By uid) order by datex desc; 
4

Volviendo la última fila de cada GROUP BY en MySQL con WHERE cláusula:

SELECT * 
FROM foo 
WHERE id IN (
    SELECT Max(id) 
    FROM foo 
    WHERE value='XYZ' 
    GROUP BY u_id 
) 
LIMIT 0,30 
1

La manera más fácil: puede seleccionar desde lista seleccionada que está ordenada.

SELECT * FROM (SELECT * FROM foo order by id DESC) AS footbl 
group by uid 
order by id DESC 
Cuestiones relacionadas