2012-02-08 13 views
14

Esiste un modo più efficiente di eseguire quanto segue?Restituire l'ultima riga di ogni "gruppo per" in MySQL

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

Questa risposta sembra simile, ma è questa risposta il miglior modo di fare questo - How to select the first row for each group in MySQL?

Grazie,

Chris.

P.S. la tabella si presenta come:

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`) 
) 

dati:

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

risultati:

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

Vedere http://www.barricane.com/2012/02/08/mysql-select-last-matching-row.html per maggiori dettagli.

+0

Questa è una sottoquery correlata. Generalmente, una sottoquery non correlata si dimostrerà più veloce, come nell'esempio di Devart. – Strawberry

+0

possibile duplicato di [Recupero dell'ultimo record in ogni gruppo] (http: // stackoverflow.it/questions/1313120/retrieving-the-last-record-in-each-group) –

risposta

33

Prova questa ricerca -

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; 

Quindi utilizzare EXPLAIN per analizzare le query.


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

Questo non funziona come vista - Ottengo "ERROR 1349 (HY000): View's SELECT contiene una sottoquery nella clausola FROM", mentre il mio codice lo fa. – fadedbee

+1

Non sapevo che lo avresti usato per la visualizzazione. ... Ne ho aggiunto un altro – Devart

+0

Grazie, dovrò fare dei test su tutte e tre le alternative e riferire. (Sono riuscito a far funzionare la prima soluzione per le viste rendendo la sottoquery una vista separata.) – fadedbee

2

se la tabella è di grandi dimensioni. Fare view contenente tutta la scorsa id fila

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

Ora si uniscono la query principale con questo view. Sarà più veloce.

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

o si può fare unirsi con le ultime registrazioni dirette nella query anche:

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

Questo ha funzionato per me, grazie!

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; 

mia versione:

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; 

questo codice qui sotto non restituisce tutte le righe che voglio perché se colonna max id è uno inattiva allora salta il gruppo, anche se il gruppo ha righe attive. .

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

Tornando l'ultima fila di ogni GROUP BY in MySQL con WHERE clausola:

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

Il modo più semplice: è possibile selezionare dall'elenco selezionato ordinato.

SELECT * FROM (SELECT * FROM foo order by id DESC) AS footbl 
group by uid 
order by id DESC 
Problemi correlati