Limiter les résultats aux 2 premières lignes de classement

22

Dans SQL Server 2008, j'utilise RANK() OVER (PARTITION BY Col2 ORDER BY Col3 DESC)pour renvoyer l'ensemble de données avec RANK. Mais j'ai des centaines d'enregistrements pour chaque partition, donc j'obtiendrai des valeurs de rang 1, 2, 3 ...... 999. Mais je veux seulement jusqu'à 2 RANKsdans chacun PARTITION.

Exemple:

ID   Name    Score    Subject
1    Joe      100      Math
2    Jim      99       Math
3    Tim      98       Math
4    Joe      99       History
5    Jim      100      History
6    Tim      89       History
7    Joe      80       Geography
8    Tim      100      Geography
9    Jim      99       Geography

Je veux que le résultat soit:

SELECT Subject, Name, RANK() OVER (PARTITION BY Subject ORDER BY Score DESC)
FROM Table
Subject        Name      Rank
Math           Joe        1
Math           Jim        2
History        Jim        1
History        Joe        2
Geography      Tim        1
Geography      Jim        2

Je veux seulement les classements 1 et 2 dans chaque catégorie. Comment puis-je faire cela?

UB01
la source

Réponses:

15

Vous pouvez placer la requête d'origine à l'aide d' rank()une sous-requête et l'encapsuler avec une requête qui filtre les résultats.

ConcernedOfTunbridgeWells
la source
Logique. Je souhaite que Microsoft le rende plus simple, c'est-à-dire qu'il insère un nombre dans la fonction RANK. RANK(2) OVER (PARTITION BY Col2 ORDER B Y Col3) AS Top_2_Ranks. Peut-être que cela se produira dans les prochaines versions. Merci pour l'idée.
UB01
@ UB01: Ou mieux encore, il serait bien d'utiliser des fonctions fenêtrées dans une WHEREclause.
Jon de tous les métiers
16
select * from (
SELECT Subject, Name, RANK() OVER (PARTITION BY Subject ORDER BY Score DESC) as RN
FROM Table
) a
where a.RN <= 2
Derek Kromm
la source
0

Je pense que la façon de le faire dans SQL Server est de combiner la fonction window avec une expression de table commune:

with cte as (
SELECT Subject, Name, RANK() OVER (PARTITION BY Subject ORDER BY Score DESC) as ordinal
FROM Table
)
select * from cte where ordinal <= 2
josebrwn
la source
-1

Pour Teradara, vous pouvez également faire:

SELECT 
Subject, 
Name, 
RANK() OVER (PARTITION BY Subject ORDER BY Score DESC) as RN
FROM Table
QUALIFY a.RN <= 2
Dimitar Nentchev
la source
3
Eh bien, cela pourrait être correct, mais la question concerne spécifiquement SQL Server.
dezso