sql >> Database >  >> RDS >> Mysql

toon laatste reactie die slechts 1 reactie per gebruiker

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 BY clausule;
  • worden gebruikt met GROUP BY geaggregeerde functies ;
  • zijn functioneel afhankelijk van de kolommen die verschijnen in de GROUP BY clausule.

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.



  1. NodeJS MSSQL WAAR IN Voorbereide SQL-instructie

  2. MySQL consolideert dubbele gegevensrecords via UPDATE / DELETE

  3. T-SQL:In tegenstelling tot tekenreeksaaneenschakeling - hoe tekenreeks in meerdere records te splitsen

  4. A.* bevindt zich niet in GROUP BY met left join op laravel-querybuilder