Dit soort zoekopdrachten kunnen worden geherformuleerd in de zin van 'grootste-n-per-groep', waarbij u wilt dat de top 10 scores per 'groep' de waarden van 'foo' zijn.
Ik stel voor dat je een kijkje neemt op deze link die deze vraag op wonderbaarlijke wijze behandelt, te beginnen met een manier die logisch is om uw zoekopdracht uit te voeren en deze geleidelijk te optimaliseren.
set @num := 0, @foo := '';
select foo, score
from (
select foo, score,
@num := if(@foo = foo, @num + 1, 1) as row_number,
@foo := foo as dummy
from tablebar
where foo IN ('abc','def')
order by foo, score DESC
) as x where x.row_number <= 10;
Als je dit voor alle wilt doen niveaus van foo
(d.w.z. stel je voor dat je een GROUP BY foo
doet ), kunt u de where foo in ...
. weglaten lijn.
In feite de innerlijke vraag (SELECT foo, score FROM tablebar WHERE foo IN ('abc','def') ORDER BY foo, score DESC
) grijpt foo
en score
van de tafel, bestel eerst bij foo
en dan aflopend scoren.
De @num := ...
verhoogt gewoon elke rij, reset naar 1 voor elke nieuwe waarde van foo
. Dat wil zeggen, @num
is slechts een rijnummer/rang (probeer de innerlijke query op zichzelf uit te voeren om te zien wat ik bedoel).
De buitenste zoekopdracht selecteert vervolgens rijen waarvan het rangnummer/rijnummer kleiner is dan of gelijk is aan 10.
OPMERKING:
Uw oorspronkelijke vraag met UNION
verwijdert duplicaten, dus als de top 10 scoort voor foo='abc'
zijn alle 100 dan wordt er slechts één rij geretourneerd (sinds de (foo,score)
paar wordt 10 keer gerepliceerd). Deze retourneert duplicaten.