2013-08-14 14 views
32

Ho problemi durante l'esecuzione di questo codice:GROUP BY MAX dover data

SELECT * FROM tblpm n 
WHERE date_updated=(SELECT MAX(date_updated) 
FROM tblpm GROUP BY control_number 
HAVING control_number=n.control_number) 

Fondamentalmente, voglio tornare alla data più recente per ciascun numero di controllo. La query sopra restituisce l'output corretto ma richiede 37sec. prima che l'output fosse mostrato.

C'è qualche altra clausola o comando sql che può essere eseguita più rapidamente della query sopra?

Grazie in anticipo.

risposta

73

Inserire la sottoquery nella clausola WHERE e limitarlo a n.control_number significa che esegue la subquery più volte. Si chiama sottoquery correlata ed è spesso un killer delle prestazioni.

È meglio eseguire la subquery una volta, nella clausola FROM, per ottenere la data massima per numero di controllo.

SELECT n.* 
FROM tblpm n 
INNER JOIN (
    SELECT control_number, MAX(date_updated) AS date_updated 
    FROM tblpm GROUP BY control_number 
) AS max USING (control_number, date_updated); 
+0

Grazie Signore! Funziona perfettamente ora :-) –

+3

mysql doc -> http://dev.mysql.com/doc/refman/5.0/en/example-maximum-column-group-row.html –

+0

@PacketTracer, grazie per il collegamento doc ! Eppure, questa domanda è stata posta più di 900 volte su StackOverflow da quando ho creato il tag [tag: greatest-n-per-group]. –

12

Non c'è bisogno di gruppo in quel subquery ... una clausola where sarebbe sufficiente:

SELECT * FROM tblpm n 
WHERE date_updated=(SELECT MAX(date_updated) 
    FROM tblpm WHERE control_number=n.control_number) 

Inoltre, si dispone di un indice sulla colonna 'date_updated'? Questo sarebbe certamente di aiuto.

+0

toooo ... buona !!! Salvavita. :) –

+2

Se la data aggiornata è la stessa (legatura), mostra entrambi i record quando si utilizza questa soluzione, quindi è necessario aggiungere 'GROUP BY n. control_number' – radtek

-3

facile e veloce con avere:

SELECT * FROM tblpm n 
FROM tblpm GROUP BY control_number 
HAVING date_updated=MAX(date_updated); 

Nel contesto di HAVING, MAX trova il massimo di ogni gruppo. Solo l'ultima voce di ciascun gruppo soddisferà date_updated=max(date_updated). Se c'è un pareggio più recente all'interno di un gruppo, entrambi passeranno il filtro HAVING, ma GROUP BY significa che solo uno verrà visualizzato nella tabella restituita.

+0

in realtà temo che questo non funzioni come previsto, ottengo un set di risultati vuoto per questa query: 'select * from order_order_status dove order_order_status.order_id = 1 group by order_order_status. order_id avendo order_order_status.created_at = max (order_order_status.created_at) 'table ha quelle voci:' INSERT INTO order_order_status (id, order_id, created_at) VALUES (1, 1, '01-10-01-0157:37 '), (2, 2, '01-10-01 01:57:54 '), (3, 3, '2012/02 02:12:49'), (4, 3, '2016-10 -02 02:14:19 '), (5, 3,' 2016-10-02 04:18:07 '), (8, 1,' 2016-10-03 01:22:53 '); ' – Toskan

+0

vorrei poter votare a valle, questo mi ha perso un po 'di tempo – Toskan

+0

questo non funziona! – Alexey

-1

Un altro modo che non fa uso di gruppo da:

SELECT * FROM tblpm n 
    WHERE date_updated=(SELECT date_updated FROM tblpm n 
         ORDER BY date_updated desc LIMIT 1)