Waarom het niet werkt met GROUP BY
SELECT * kan niet worden gebruikt met GROUP BY; het is een ongeldige SQL. GROUP BY selecteert geen tabelrijen. Het maakt groepen rijen met behulp van de opgegeven uitdrukkingen en genereert vervolgens van elke groep een nieuw record en berekent elke kolom van dit nieuwe record met behulp van de waarden die bij de uitdrukking betrokken zijn.
De kolommen die verschijnen in de SELECT clausule moet aan een van de volgende regels voldoen:
- verschijnen ook in de
GROUP BYclausule; - worden gebruikt met
GROUP BYgeaggregeerde functies ; - zijn functioneel afhankelijk van de kolommen die verschijnen in de
GROUP BYclausule.
Terwijl * is een snelkoppeling voor alle kolomnamen van de tabel(len) die door de zoekopdracht worden gebruikt, voor uw zoekopdracht alleen de user kolom voldoen aan een van de bovenstaande vereisten.
Vóór versie 5.7.5
MySQL heeft de derde regel hierboven niet geïmplementeerd. Vroeger accepteerde het zoekopdrachten die in de SELECT clausulekolommen die niet volgen op een van de GROUP BY vereisten. De waarde die door de zoekopdracht voor dergelijke kolommen werd geretourneerd, was onbepaald
.
Sinds versie 5.7.5 weigert MySQL de GROUP BY zoekopdrachten die wel aan de vereisten voldoen.
De oplossing
Hoe dan ook, de oplossing voor uw probleem is niet GROUP BY . Het kan eenvoudig worden bereikt met een LEFT JOIN met de juiste voorwaarden:
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
Hoe het werkt
Het voegt zich bij de tabel comments , alias lc ("lc" van de "laatste opmerking" van een gebruiker) tegen zichzelf, alias nc ("nc" van "nieuwere opmerking"). De join-clausule komt overeen met elke invoer van lc met alle vermeldingen van nc die bij dezelfde gebruiker horen (lc.user = nc.user ) en zijn nieuwer (lc.id < nc.id; Ik nam aan dat de ID's opeenvolgend worden toegewezen en dat nieuwere opmerkingen grotere waarden hebben voor id ).
Het gebruik van LEFT JOIN zorgt ervoor dat elke rij van lc verschijnt in het resultaat van de samenvoeging, zelfs als er geen overeenkomende rij is gevonden in nc (omdat er geen nieuwere opmerking van dezelfde gebruiker is). In dit geval NULL wordt gebruikt in plaats van de velden van nc . De WHERE clausule behoudt in de uiteindelijke resultaatset alleen de rijen die NULL . hebben in nc.id; dit betekent in de lc deel bevatten ze de meest recente opmerking van elke gebruiker.
De SELECT clausule bevat alle velden van lc (die van nc zijn allemaal NULL , hoe dan ook). De ORDER BY clausule kan worden gebruikt om de resultatenset te sorteren. ORDER BY lc.id DESC plaatst de meest recente opmerkingen eerst en de LIMIT clausule houdt het resultaat ingesteld op een behoorlijke omvang.