sql >> Database >  >> RDS >> Mysql

Meerdere query's uitvoeren in MySQL zonder subquery te gebruiken

Het werkt niet zoals je denkt dat het zou moeten en de documentatie verklaart de betekenis van DISTINCT :het gaat om verschillende rijen :

(bron:http://dev.mysql.com /doc/refman/5.7/nl/select.html )

U moet de rijen per gebruiker groeperen om een ​​enkele rij voor elke gebruiker te krijgen, maar helaas kunt u op deze manier hun meest recente score niet krijgen. U kunt de maximale, minimale, gemiddelde score en andere berekende waarden krijgen. Bekijk de lijst met GROUP BY geaggregeerde functies .

De vraag

Dit is de query die de gewenste waarden ophaalt:

SELECT u.fsname, u.emailaddress, la.score 
FROM users u
INNER JOIN attempts la                # 'la' from 'last attempt'
    ON u.emailaddress = la.emailaddress
LEFT JOIN attempts mr                 # 'mr' from 'more recent' (than last attempt)
    ON la.emailaddress = mr.emailaddress AND la.datetime < mr.datetime
WHERE mr.datetime IS NULL

Hoe het werkt

Het voegt zich bij tabel users (alias u ) met tabel attempts (alias la , een afkorting voor "laatste poging") met behulp van emailaddress als de overeenkomende kolom. Het is de join die je al hebt in je zoekopdracht, ik heb de aliassen toegevoegd omdat ze je vanaf dat moment helpen minder te schrijven.

Vervolgens voegt het zich bij de attempts tabel opnieuw (alias mr) van "meer recent dan de laatste poging"). Het komt overeen met elke poging van la met alle pogingen van mr van dezelfde gebruiker (geïdentificeerd door hun emailaddress ) en die een recentere datetime . hebben . De LEFT JOIN zorgt ervoor dat elke rij van la komt overeen met ten minste één rij van mr . De rijen van la die geen overeenkomst hebben in mr zijn de rijen met de grootste waarden van datetime voor elk emailaddress . Ze worden gekoppeld aan rijen vol met NULL (voor de mr deel).

Eindelijk, de WHERE clausule behoudt alleen de rijen die NULL . hebben in de datetime kolom van de rij geselecteerd uit mr . Dit zijn de rijen die overeenkwamen met de meest recente invoer van la voor elke waarde van emailaddress .

Opmerkingen over prestaties

Om deze zoekopdracht snel uit te voeren (elke zoekopdracht! ) heeft indexen nodig voor de kolommen die worden gebruikt in de JOIN , WHERE , GROUP BY en ORDER BY clausules.

Gebruik geen emailaddress in tabel attempts om de gebruiker te identificeren. Je zou een PK . moeten hebben (primaire sleutel) op tafel users en gebruik dat als een FK (vreemde sleutel) in tabel attempts (en andere tabellen die naar een gebruiker verwijzen). Als emailaddress is de PK van tabel users verander het in een UNIQUE INDEX en gebruik een nieuwe INTEGER AUTO INCREMENT ed kolom userId als PK in plaats van. De indexen op numerieke kolommen zijn sneller en nemen minder ruimte in beslag dan de indexen op stringkolommen.




  1. Hoe kan ik een automatische e-mail verzenden vanuit MySQL-records?

  2. SELECT-lijst staat niet in GROUP BY-clausule en bevat niet-geaggregeerde kolom .... incompatibel met sql_mode=only_full_group_by

  3. Het optimaliseren van een SELECT-query die langzaam draait op Oracle die snel draait op SQL Server

  4. MySQL aangepaste volgorde