Question

J'aimerais trouver les différentes façons de résoudre un problème réel que j'ai rencontré :imaginez organiser un concours, ou un jeu, au cours duquel les utilisateurs collectent des points.Vous devez créer une requête pour afficher la liste des utilisateurs avec les meilleurs scores « n ».

Je fais un exemple pour clarifier.Disons qu'il s'agit du tableau Utilisateurs, avec les points gagnés :

UserId - Points
1      - 100
2      -  75
3      -  50
4      -  50
5      -  50
6      -  25

Si je veux les 3 meilleurs scores, le résultat sera :

UserId - Points
1      - 100
2      -  75
3      -  50
4      -  50
5      -  50

Cela peut être réalisé dans une vue ou une procédure stockée, comme vous le souhaitez.Ma base de données cible est SQL Server.En fait, j'ai résolu ce problème, mais je pense qu'il existe différentes manières d'obtenir le résultat...plus rapide ou plus efficace que le mien.

Était-ce utile?

La solution

Non testé, mais devrait fonctionner :

select * from users where points in
(select distinct top 3 points from users order by points desc)

Autres conseils

En voici un qui fonctionne - je ne sais pas s'il est plus efficace, et c'est SQL Server 2005+

with scores as (
    select 1 userid, 100 points
    union select 2, 75
    union select 3, 50
    union select 4, 50
    union select 5, 50
    union select 6, 25
),
results as (
    select userid, points, RANK() over (order by points desc) as ranking 
    from scores
)
select userid, points, ranking
from results
where ranking <= 3

Évidemment, le premier "avec" consiste à configurer les valeurs, vous pouvez donc tester le second avec et sélectionner le travail final - vous pouvez commencer par "avec les résultats comme..." si vous interrogez une table existante.

Que diriez-vous:

select top 3 with ties points 
from scores
order by points desc

Je ne sais pas si "avec des liens" fonctionne sur autre chose que SQL Server.

Sur SQL Server 2005 et versions ultérieures, vous pouvez transmettre le numéro « supérieur » en tant que paramètre int :

select top (@n) with ties points 
from scores
order by points desc

En fait, une modification du WHERE IN, en utilisant un INNER JOIN sera beaucoup plus rapide.

SELECT 
   userid, points 
FROM users u
INNER JOIN 
(
   SELECT DISTINCT TOP N 
      points 
   FROM users 
   ORDER BY points DESC
) AS p ON p.points = u.points

@bosnic, je ne pense pas que cela fonctionnera comme demandé, je ne suis pas très familier avec MS SQL mais je m'attendrais à ce qu'il ne renvoie que 3 lignes et ignore le fait que 3 utilisateurs sont à égalité pour la 3ème place.

Quelque chose comme ceci devrait fonctionner :

select userid, points 
   from scores 
   where points in (select top 3 points 
                       from scores 
                       order by points desc) 
   order by points desc

@Rob#37760 :

select top N points from users order by points desc

Cette requête ne sélectionnera que 3 lignes si N vaut 3, voir la question."Top 3" devrait renvoyer 5 lignes.

@Espo merci pour la vérification de la réalité - ajout de la sous-sélection pour corriger cela.

Je pense que la réponse la plus simple est de :

select userid, points from users
where points in (select distinct top N points from users order by points desc) 

Si vous souhaitez mettre cela dans un processus stocké qui prend N comme paramètre, vous devrez alors soit lire le SQL dans une variable puis l'exécuter, soit effectuer l'astuce du nombre de lignes :

declare @SQL nvarchar(2000)
set @SQL = "select userID, points from users "
set @SQL = @SQL + " where points in (select distinct top " + @N
set @SQL = @SQL + " points from users order by points desc)"

execute @SQL

ou

SELECT  UserID, Points
FROM     (SELECT  ROW_NUMBER() OVER (ORDER BY points DESC)
         AS Row, UserID, Points FROM Users)
        AS usersWithPoints
WHERE  Row between 0 and @N

Les deux exemples supposent SQL Server et n'ont pas été testés.

@Matt Hamilton

Votre réponse fonctionne avec l'exemple ci-dessus mais ne fonctionnerait pas si l'ensemble de données était de 100, 75, 75, 50, 50 (où il ne renverrait que 3 lignes).TOP AVEC LIENS ne comprend que les liens du dernier rang retourné...

Crucible l'a obtenu (en supposant que SQL 2005 soit une option).

Hé, j'ai trouvé toutes les autres réponses un peu long et inefficace, ma réponse serait:

select * from users order by points desc limit 0,5

cela rendra les 5 meilleurs points

Essaye ça

select top N points from users order by points desc
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top