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 BY
Klausel; - werden mit
GROUP BY
Aggregatfunktionen ; - sind funktional abhängig von den Spalten, die in
GROUP BY
erscheinen 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.