Warum es mit GROUP BY nicht funktioniert
SELECT * kann nicht mit GROUP BY verwendet werden; es ist ungültiges SQL. GROUP BY wählt keine Tabellenzeilen aus. Es erstellt Gruppen von Zeilen unter Verwendung der bereitgestellten Ausdrücke, generiert dann aus jeder Gruppe einen neuen Datensatz und berechnet jede Spalte dieses neuen Datensatzes unter Verwendung der im Ausdruck enthaltenen Werte.
Die Spalten, die in SELECT erscheinen -Klausel muss eine der folgenden Regeln erfüllen:
- erscheinen auch im
GROUP BYKlausel; - werden mit
GROUP BYAggregatfunktionen ; - sind funktional abhängig von den Spalten, die in
GROUP BYerscheinen Klausel.
Während * ist eine Abkürzung für alle Spaltennamen der von der Abfrage verwendeten Tabelle(n), für Ihre Abfrage nur der user Spalte eine der oben genannten Anforderungen erfüllen.
Vor Version 5.7.5
MySQL hat die dritte obige Regel nicht implementiert. Früher akzeptierte es Abfragen, die im SELECT enthalten waren Klauselspalten, die keinem der GROUP BY folgen Bedarf. Der von der Abfrage für solche Spalten zurückgegebene Wert war unbestimmt
.
Seit Version 5.7.5 lehnt MySQL das GROUP BY ab Abfragen, die die Anforderungen erfüllen.
Die Lösung
Wie auch immer, die Lösung für Ihr Problem beinhaltet nicht GROUP BY . Dies kann leicht mit einem LEFT JOIN erreicht werden mit den richtigen Bedingungen:
SELECT lc.*
FROM comments lc # 'lc' from 'last comment'
LEFT JOIN comments nc # 'nc' from 'newer comment'
ON lc.user = nc.user # both comments belong to the same user
AND lc.id < nc.id # 'nc' is newer than 'lc'
WHERE nc.id IS NULL # there is no 'newer comment'
ORDER BY lc.id DESC
LIMIT 10
Wie es funktioniert
Es schließt sich der Tabelle comments an , mit dem Alias lc ("lc" aus dem "letzten Kommentar" eines Benutzers) gegen sich selbst, aliasiert als nc ("nc" von "neuerer Kommentar"). Die Join-Klausel passt zu jedem Eintrag von lc mit allen Einträgen von nc die demselben Benutzer gehören (lc.user = nc.user ) und sind neuer (lc.id < nc.id; Ich bin davon ausgegangen, dass die IDs nacheinander zugewiesen werden und neuere Kommentare größere Werte für id haben ).
Die Verwendung von LEFT JOIN stellt sicher, dass jede Zeile von lc erscheint im Ergebnis des Joins, selbst wenn keine übereinstimmende Zeile in nc gefunden wird (weil es keinen neueren Kommentar desselben Benutzers gibt). In diesem Fall NULL wird anstelle der Felder von nc verwendet . Das WHERE -Klausel behält in der endgültigen Ergebnismenge nur die Zeilen mit NULL in nc.id; das heißt im lc teilweise enthalten sie den neuesten Kommentar jedes Benutzers.
Die SELECT -Klausel enthält alle Felder von lc (die von nc sind alle NULL , ohnehin). Der ORDER BY -Klausel kann verwendet werden, um die Ergebnismenge zu sortieren. ORDER BY lc.id DESC setzt die neuesten Kommentare zuerst und das LIMIT -Klausel hält die Ergebnismenge auf einer anständigen Größe.