Come posso vedere, devi classificare le tue righe in un modo più sofisticato, in modo che le voci che sono le prime in ogni categoria siano incluse indipendentemente dai loro valori e le voci che non sono le prime siano incluse in base al loro totale classifiche.
Quella che sto per suggerire potrebbe non essere la soluzione più efficiente, ma dovrebbe funzionare e, se non altro, potrebbe ispirare qualcun altro a inventare qualcosa di meglio:
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
;
Il primo CTE classifica le righe per categorie, permettendoci così di scoprire quali voci diventano le prime nelle rispettive categorie. Il passaggio successivo (secondo CTE) riguarda l'ottenimento di classifiche globali, questa volta tenendo conto se una voce è la prima nella sua categoria o meno. I primi valori della categoria ricevono classifiche inferiori e quindi sono assicurati per essere inclusi nei risultati finali. (Naturalmente, devi assicurarti che il numero di categorie non sia maggiore del numero di valori distinti che desideri ricevere nell'output.)
Ecco un esempio dal vivo su SQL Fiddle con cui giocare.