Denne form for forespørgsel kan omformuleres i en "største-n-pr-gruppe" forstand, hvor du ønsker, at de 10 bedste resultater pr. "gruppe" skal være værdierne for "foo".
Jeg foreslår, at du tager et kig på dette link der behandler dette spørgsmål fantastisk, og starter med en måde, der giver mening at udføre din forespørgsel på og gradvist optimere 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;
Hvis du ville udføre dette på tværs af alle niveauer af foo
(dvs. forestil dig at lave en GROUP BY foo
), kan du udelade where foo in ...
linje.
Dybest set den indre forespørgsel (SELECT foo, score FROM tablebar WHERE foo IN ('abc','def') ORDER BY foo, score DESC
) griber foo
og score
fra bordet ved at bestille først efter foo
og derefter score faldende.
@num := ...
øger bare hver række og nulstiller til 1 for hver ny værdi af foo
. Det vil sige @num
er kun et rækkenummer/rangering (prøv at køre den indre forespørgsel alene for at se, hvad jeg mener).
Den ydre forespørgsel vælger derefter rækker, hvor rang-/rækkenummeret er mindre end eller lig med 10.
BEMÆRK:
Din oprindelige forespørgsel med UNION
fjerner dubletter, så hvis top 10 scorer for foo='abc'
er alle 100, vil kun én række blive returneret (da (foo,score)
par er replikeret 10 gange). Denne vil returnere dubletter.