Wie ich sehe, müssen Sie Ihre Zeilen differenzierter ordnen, sodass Einträge, die in jeder Kategorie die besten sind, unabhängig von ihren Werten enthalten sind, und Einträge, die nicht die besten sind, entsprechend ihrer Gesamtzahl enthalten sind Rankings.
Was ich gleich vorschlagen werde, ist vielleicht nicht die effizienteste Lösung, aber es sollte funktionieren und, wenn nichts anderes kann, vielleicht jemand anderen dazu inspirieren, sich etwas Besseres auszudenken:
WITH ranked1 AS (
SELECT
*,
RankByCategory = DENSE_RANK() OVER (
PARTITION BY CategoryID
ORDER BY Score DESC
)
FROM YourTable
),
ranked2 AS (
SELECT
*,
FinalRank = DENSE_RANK() OVER (
ORDER BY
CASE RankByCategory WHEN 1 THEN 1 ELSE 2 END,
Score DESC
)
FROM ranked1
)
SELECT
EntryID,
CategoryID,
Score
FROM ranked2
WHERE FinalRank <= @top_n
;
Der erste CTE ordnet Zeilen nach Kategorien und lässt uns so herausfinden, welche Einträge die besten in ihren jeweiligen Kategorien werden. Im nächsten Schritt (zweiter CTE) geht es darum, globale Rankings zu erhalten, diesmal unter Berücksichtigung, ob ein Eintrag der beste in seiner Kategorie ist oder nicht. Die Top-Werte der Kategorie erhalten niedrigere Platzierungen und werden somit sicher in die Endergebnisse aufgenommen. (Natürlich müssen Sie sicherstellen, dass die Anzahl der Kategorien nicht größer ist als die Anzahl der eindeutigen Werte, die Sie in der Ausgabe erhalten möchten.)
Hier ist ein Live-Beispiel bei SQL Fiddle zum Spielen.