Dlaczego nie działa z GROUP BY
SELECT *
nie może być używany z GROUP BY
; jest to nieprawidłowy SQL. GROUP BY
nie zaznacza wierszy tabeli. Tworzy grupy wierszy przy użyciu dostarczonych wyrażeń, a następnie z każdej grupy generuje nowy rekord i oblicza każdą kolumnę tego nowego rekordu przy użyciu wartości zawartych w wyrażeniu.
Kolumny, które pojawiają się w SELECT
klauzula musi spełniać jedną z następujących zasad:
- pojawiają się również w
GROUP BY
klauzula; - są używane z
GROUP BY
funkcje agregujące ; - są funkcjonalnie zależne od kolumn, które pojawiają się w
GROUP BY
klauzula.
Podczas gdy *
jest skrótem do wszystkich nazw kolumn w tabelach używanych przez zapytanie, w zapytaniu tylko user
kolumna spełnia jedno z powyższych wymagań.
Przed wersją 5.7.5
MySQL nie zaimplementował trzeciej reguły powyżej. Służy do akceptowania zapytań, które zawierają w SELECT
kolumny klauzul, które nie następują po żadnej z GROUP BY
wymagania. Wartość zwrócona przez zapytanie dla takich kolumn była nieokreślona
.
Od wersji 5.7.5 MySQL odrzuca GROUP BY
zapytania, które spełniają wymagania.
Rozwiązanie
Tak czy inaczej, rozwiązanie Twojego problemu nie obejmuje GROUP BY
. Można to łatwo wykonać za pomocą LEFT JOIN
z prawidłowymi warunkami:
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
Jak to działa
Łączy się z tabelą comments
, alias lc
(„lc” z „ostatniego komentarza” użytkownika) przeciwko sobie, aliasem nc
("nc" od "nowszego komentarza"). Klauzula join pasuje do każdego wpisu lc
ze wszystkimi wpisami nc
należące do tego samego użytkownika (lc.user = nc.user
) i są nowsze (lc.id < nc.id
; Założyłem, że identyfikatory są przypisywane sekwencyjnie, a nowsze komentarze mają większe wartości dla id
).
Użycie LEFT JOIN
zapewnia, że każdy wiersz lc
pojawia się w wyniku złączenia, nawet jeśli nie znaleziono pasującego wiersza w nc
(ponieważ nie ma nowszego komentarza tego samego użytkownika). W tym przypadku NULL
jest używany zamiast pól nc
. WHERE
klauzula przechowuje w końcowym zestawie wyników tylko te wiersze, które mają NULL
w nc.id
; oznacza to w lc
część zawierają najnowsze komentarze każdego użytkownika.
SELECT
klauzula zawiera wszystkie pola lc
(te z nc
są wszystkie NULL
, w każdym razie). ORDER BY
Klauzula może służyć do sortowania zestawu wyników. ORDER BY lc.id DESC
umieszcza najnowsze komentarze jako pierwsze, a LIMIT
klauzula utrzymuje wynik ustawiony na przyzwoity rozmiar.