2013-08-14 6 views
32

Ich habe Probleme, wenn Sie diesen Code ausführen:GROUP BY mit MAX Datum

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

Grundsätzlich mag ich das letzte Datum für jede Kontrollnummer zurückzukehren. Die obige Abfrage gibt die korrekte Ausgabe zurück, aber es dauert 37 Sekunden. bevor die Ausgabe angezeigt wurde.

Gibt es eine andere sql-Klausel oder einen anderen Befehl, der schneller als die obige Abfrage ausgeführt werden kann?

Vielen Dank im Voraus.

Antwort

73

Wenn Sie die Unterabfrage in die WHERE-Klausel setzen und sie auf n.control_number beschränken, bedeutet dies, dass die Unterabfrage mehrmals ausgeführt wird. Dies wird korrelierte Unterabfrage genannt, und es ist oft ein Performance-Killer.

Es ist besser, die Unterabfrage in der FROM-Klausel einmal auszuführen, um das maximale Datum pro Kontrollnummer zu erhalten.

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

Danke Sir! Es funktioniert jetzt perfekt :-) –

+3

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

+0

@PacketTracer, danke für den doc Link ! Und doch wurde diese Frage mehr als 900 Mal in StackOverflow gestellt, seit ich das Tag [tag: greatest-n-per-group] erstellt habe. –

12

Es gibt keine Notwendigkeit zu einer Gruppe in dieser Unterabfrage ... eine where-Klausel würde genügen:

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

Auch, haben Sie einen Index für die ‚date_updated‘ Spalte? Das würde sicherlich helfen.

+0

... good !!! Lebensretter. :) –

+2

Wenn das aktualisierte Datum gleich ist (tie), zeigt es beide Datensätze an, wenn Sie diese Lösung verwenden, daher müssen Sie 'GROUP BY n hinzufügen. control_number' – radtek

-3

Schnell und einfach mit HAVING:

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

Im Rahmen der HAVING findet MAX den max jede Gruppe. Nur der letzte Eintrag in jeder Gruppe erfüllt date_updated=max(date_updated). Wenn es innerhalb einer Gruppe einen Gleichstand für den letzten gibt, werden beide den Filter passieren, aber GROUP BY bedeutet, dass nur einer in der zurückgegebenen Tabelle erscheint.

+0

eigentlich befürchte ich, das funktioniert nicht wie erwartet, bekomme ich eine leere Ergebnismenge für diese Abfrage: 'wählen * aus order_order_status wo order_order_status.order_id = 1 Gruppe von order_order_status. order_id having order_order_status.created_at = max (order_order_status.created_at) Die Tabelle enthält folgende Einträge: 'INSERT INTO order_order_status (ID, Bestell_ID, Erstelldatum) VALUES (1, 1, '2016-10-01 01:57:37'), (2, 2, '2016-10-01 01:57:54'), (3, 3, '2016-10-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

Ich wünschte, ich könnte Downvote, verlor mich einige Zeit – Toskan

+0

dies funktioniert nicht! – Alexey

-1

Eine weitere Möglichkeit, die Gruppe von nicht verwenden: toooo

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