Varför det inte fungerar med GROUP BY
SELECT *
kan inte användas med GROUP BY
; det är ogiltig SQL. GROUP BY
väljer inte tabellrader. Den skapar grupper av rader med hjälp av de angivna uttrycken och sedan, från varje grupp, genererar den en ny post och beräknar varje kolumn i denna nya post med hjälp av värdena som är involverade i uttrycket.
Kolumnerna som visas i SELECT
klausul måste uppfylla en av följande regler:
- visas även i
GROUP BY
klausul; - används med
GROUP BY
samla funktioner ; - är funktionellt beroende av kolumnerna som visas i
GROUP BY
klausul.
Medan *
är en genväg för alla kolumnnamn för tabellen/tabellerna som används av frågan, för din fråga är endast user
kolumnen uppfyller ett av kraven ovan.
Före version 5.7.5
MySQL implementerade inte den tredje regeln ovan. Det brukade acceptera frågor som innehåller SELECT
satskolumner som inte följer någon av GROUP BY
krav. Värdet som returnerades av frågan för sådana kolumner var obestämt
.
Sedan version 5.7.5 avvisar MySQL GROUP BY
frågor som uppfyller kraven.
Lösningen
Hur som helst, lösningen på ditt problem involverar inte GROUP BY
. Det kan enkelt göras med en LEFT JOIN
med rätt villkor:
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
Så fungerar det
Den förenar tabellen comments
, alias som lc
("lc" från den "sista kommentaren" av en användare) mot sig själv, alias som nc
("nc" från "nyare kommentar"). Join-satsen matchar varje post i lc
med alla inmatningar av nc
som tillhör samma användare (lc.user = nc.user
) och är nyare (lc.id < nc.id
; Jag antog att ID:n tilldelas sekventiellt och nyare kommentarer har större värden för id
).
Användningen av LEFT JOIN
säkerställer att varje rad av lc
visas i resultatet av sammanfogningen, även när ingen matchande rad hittas i nc
(eftersom det inte finns någon nyare kommentar från samma användare). I det här fallet NULL
används istället för fälten för nc
. WHERE
satsen behåller i den slutliga resultatuppsättningen endast de rader som har NULL
i nc.id
; detta betyder i lc
del innehåller de den senaste kommentaren från varje användare.
SELECT
klausulen innehåller alla fält i lc
(de av nc
är alla NULL
, i alla fall). ORDER BY
klausul kan användas för att sortera resultatuppsättningen. ORDER BY lc.id DESC
sätter de senaste kommentarerna först och LIMIT
klausul håller resultatet inställt på en anständig storlek.