Tento druh dotazu lze přeformulovat ve smyslu „greatest-n-per-group“, kde chcete, aby prvních 10 skóre na „skupinu“ byly hodnoty „foo“.
Navrhuji, abyste se podívali na tento odkaz který se s touto otázkou vypořádává úžasně, začíná způsobem, který dává smysl provést váš dotaz, a postupně jej optimalizuje.
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;
Pokud jste to chtěli provést napříč všemi úrovně foo
(tj. představte si, že děláte GROUP BY foo
), můžete vynechat where foo in ...
řádek.
V podstatě vnitřní dotaz (SELECT foo, score FROM tablebar WHERE foo IN ('abc','def') ORDER BY foo, score DESC
) popadne foo
a score
z tabulky, nejprve seřaďte podle foo
a poté skóre sestupně.
@num := ...
jen se zvyšuje každý řádek a resetuje se na 1 pro každou novou hodnotu foo
. To znamená @num
je pouze číslo řádku/hodnocení (zkuste spustit vnitřní dotaz samostatně, abyste viděli, co tím myslím).
Vnější dotaz pak vybere řádky, kde je číslo pořadí/řádku menší nebo rovno 10.
POZNÁMKA:
Váš původní dotaz s UNION
odstraní duplikáty, takže pokud 10 nejlepších skóre pro foo='abc'
je všech 100, bude vrácen pouze jeden řádek (protože (foo,score)
pár se replikuje 10krát). Tento vrátí duplikáty.