2010-01-26 6 views
3

J'ai une énorme liste classée par différentes valeurs (scores par exemple.)Classement dans Django ORM ou SQL?

Je prends la liste par ces valeurs:

players = Player.objects.order_by('-score', '-karma') 

Je voudrais:

  • Prenez un joueur et obtenez le joueurs voisins

score P1: 123

score P2: 122

VOUS! score:

score P3: 90

score P2: 89

  • Saisissez la position de !

Vous sont classés # 1234 pour le score

Vous # 9876 pour classé karma


aide serait très apprécié. merci :)

Répondre

1

Pour obtenir le classement de l'utilisateur:

(SELECT * FROM (
    SELECT 
    RANK() OVER (ORDER BY Score desc ,Karma desc) AS ranking, 
    Id, 
    Username, 
    Score, karma 
    FROM Players 
) AS players_ranked_by_score 
where Id = id_of_user 

Où id_of_user est le paramètre contenant l'identifiant du joueur actuel. Pour obtenir les joueurs voisins et l'utilisateur actuel:

(SELECT * FROM (
    SELECT 
    RANK() OVER (ORDER BY Score desc ,Karma desc) AS ranking, 
    Id, 
    Username, 
    Score, karma 
    FROM Players 
) AS all_players_ranked 
where ranking >= player_ranking - 2 and ranking <= player_ranking + 2; 

Où player_ranking est le classement obtenu à partir de la requête ci-dessus.

J'espère que ça aide!

Mise à jour: MySQL n'a pas de fonction rank() (MS SQL, Oracle, Postgres en ont un).J'ai regardé autour et j'ai eu ce lien expliquant comment faire un classement dans MySQL: http://www.artfulsoftware.com/infotree/queries.php?&bw=1024#460.

+1

'RANK()' semble être une extension spécifique à SQL Server. Ce n'est pas disponible dans la plupart des dialectes SQL. –

+0

Merci réponse génial! Btw @Daniel ne peut pas trouver RANK() dans la référence MySQL, diriez-vous que le dialecte MySQL supporte cela? – RadiantHex

+1

Ce n'est pas seulement SQL Server; Postgres 8.4 inclut également RANK(). Ne sait pas à propos de MySQL; Je pense qu'au moins, il a quelque chose de similaire. –

8

Ces sortes de choses sont toujours très difficiles à faire. Vous aurez besoin de plusieurs requêtes pour chacun. Donc, pour obtenir les joueurs juste avant et après votre position quand ils sont classés par score, vous devez d'abord déterminer quelle est cette position. (Notez que cela suppose que vous ne pouvez pas avoir plus d'une personne avec le même score, ce qui peut ne pas être nécessairement vrai.)

me = Player.objects.get(pk=my_pk) 
position = Players.objects.all().filter(
          score__lte=me.score).order_by('-score').count() 

players = Players.objects.all()[position-2:position+2] 
+0

Merci Daniel. Ceci est une réponse très utile! – RadiantHex

+1

- vous n'avez pas besoin de tout(), il suffit d'appliquer le filtre - score__lt fonctionne mieux pour le classement (score égal -> rang égal) - en dernière partie, le résultat n'est pas ordonné, donc la position n'aiderait pas, vous devrait le commander en premier - si la position <2, il y aura une exception, vous devez fixer le minimum de la position 2 à 0 (la partie haute est correcte) –

0

Je l'ai fait avec 3 requêtes avec ORM, mais je pense que moins nombre de requêtes serait mieux:

user_rank = Score.objects.filter(high_score__gt=user_score.high_score).count() + 1 

neighbour_scores = Score.objects.filter(game_id=gme,~Q(user_id = usr),high_score__gte=user_score.high_score).order_by('high_score')[:offset] 
neighbour_scores.append(user_score) 
neighbour_scores.append(Score.objects.filter(game_id=gme, high_score__lt=user_score.high_score).order_by('-high_score')[:offset]) 
Questions connexes