Sqlserver
 sql >> Database >  >> RDS >> Sqlserver

MSSQL Seleziona i primi 10 punteggi vincenti, inclusi i pareggi e almeno uno per ciascuna categoria

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.