Som jeg kan se det, skal du rangere dine rækker på en mere sofistikeret måde, så poster, der er de øverste i hver kategori, inkluderes uanset deres værdier, og poster, der ikke er de øverste, inkluderes i henhold til deres samlede placeringer.
Det, jeg er ved at foreslå, er måske ikke den mest effektive løsning, men det burde virke, og hvis intet andet kan, kan det måske inspirere en anden til at finde på noget bedre:
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
;
Den første CTE rangerer rækker efter kategorier, og lader os således finde ud af, hvilke poster der bliver de bedste i deres respektive kategorier. Næste trin (anden CTE) handler om at opnå globale placeringer, denne gang under hensyntagen til, om en post er den øverste i sin kategori eller ej. Kategoriens topværdier får lavere placeringer og er dermed sikret med i de endelige resultater. (Selvfølgelig skal du sørge for, at antallet af kategorier ikke er større end antallet af distinkte værdier, du ønsker at modtage i outputtet.)
Her er et liveeksempel på SQL Fiddle at lege med.