Diese Art von Abfrage kann im Sinne von „größte n pro Gruppe“ umformuliert werden, wobei Sie möchten, dass die Top-10-Ergebnisse pro „Gruppe“ Werte von „foo“ sind.
Ich schlage vor, Sie werfen einen Blick auf dieser Link die sich wunderbar mit dieser Frage auseinandersetzt, indem sie mit einer sinnvollen Art und Weise beginnt, Ihre Abfrage durchzuführen, und sie schrittweise optimiert.
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;
Wenn Sie dies für alle durchführen möchten Ebenen von foo
(d.h. stellen Sie sich vor, Sie machen ein GROUP BY foo
), können Sie where foo in ...
weglassen Linie.
Grundsätzlich die innere Abfrage (SELECT foo, score FROM tablebar WHERE foo IN ('abc','def') ORDER BY foo, score DESC
) greift foo
und score
aus der Tabelle, zuerst nach foo
bestellen und dann Punktzahl absteigend.
Der @num := ...
erhöht einfach jede Zeile und wird für jeden neuen Wert von foo
auf 1 zurückgesetzt . Das heißt, @num
ist nur eine Zeilennummer/Rang (versuchen Sie, die innere Abfrage selbst auszuführen, um zu sehen, was ich meine).
Die äußere Abfrage wählt dann Zeilen aus, bei denen die Rang-/Zeilennummer kleiner oder gleich 10 ist.
HINWEIS:
Ihre ursprüngliche Anfrage mit UNION
entfernt Duplikate, also wenn die Top 10 für foo='abc'
punkten alle 100 sind, wird nur eine Zeile zurückgegeben (da der (foo,score)
Paar wird 10 Mal repliziert). Dieser gibt Duplikate zurück.