Som jag kan se det måste du rangordna dina rader på ett mer sofistikerat sätt, så att poster som är de bästa i varje kategori inkluderas oavsett deras värden, och poster som inte är de översta inkluderas enligt deras övergripande ranking.
Det jag ska föreslå kanske inte är den mest effektiva lösningen, men det borde fungera och, om inget annat kan, kan det inspirera någon annan att komma på något bättre:
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örsta CTE rangordnar rader efter kategorier, vilket låter oss ta reda på vilka bidrag som blir de bästa i sina respektive kategorier. Nästa steg (andra CTE) handlar om att få global ranking, denna gång med hänsyn till om ett bidrag är det bästa i sin kategori eller inte. Kategorin toppvärden får lägre ranking och är därmed säkerställda att inkluderas i slutresultaten. (Naturligtvis måste du se till att antalet kategorier inte är större än antalet distinkta värden du vill ta emot i utdata.)
Här är ett liveexempel på SQL Fiddle att leka med.