Den här typen av sökning kan omformuleras i "största-n-per-grupp", där du vill att de 10 bästa poängen per "grupp" ska vara värdena för "foo".
Jag föreslår att du tar en titt på denna länk som hanterar denna fråga fantastiskt, börjar med ett sätt som är vettigt att utföra din fråga och gradvis optimera den.
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;
Om du ville utföra detta i alla nivåer av foo
(dvs. tänk dig att göra en GROUP BY foo
), kan du utelämna where foo in ...
rad.
I grund och botten den inre frågan (SELECT foo, score FROM tablebar WHERE foo IN ('abc','def') ORDER BY foo, score DESC
) tar tag i foo
och score
från bordet, beställ först efter foo
och sedan poäng fallande.
@num := ...
ökar bara varje rad och återställer till 1 för varje nytt värde på foo
. Det vill säga @num
är bara ett radnummer/rang (försök att köra den inre frågan på egen hand för att se vad jag menar).
Den yttre frågan väljer sedan rader där rang-/radnumret är mindre än eller lika med 10.
OBS:
Din ursprungliga fråga med UNION
tar bort dubbletter, så om de 10 bästa poängen för foo='abc'
är alla 100 kommer bara en rad att returneras (eftersom (foo,score)
paret replikeras 10 gånger). Den här kommer att returnera dubbletter.