Classement au sein de Django ORM ou SQL?
-
22-09-2019 - |
Question
J'ai une énorme liste classée par différentes valeurs (par exemple. Scores)
Je prends la liste par ces valeurs:
players = Player.objects.order_by('-score', '-karma')
Je voudrais:
- Prenez un joueur et obtenir les joueurs voisins
score P1: 123
score P2: 122
! score: 110
score P3: 90
score P2: 89
- Saisissez le Position
Vous êtes classé # 1234 pour le score
Vous êtes classé # 9876 pour karma
L'aide serait très apprécié. merci:)
La solution
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 demande de recherche ci-dessus.
it helps!
Mise à jour : MySQL n'a pas de fonction rang () (MS SQL, Oracle, Postgres ont un). Je regardais autour et je suis arrivé ce lien expliquant comment faire le classement dans MySQL: http://www.artfulsoftware.com/infotree/queries.php?&bw=1024#460 .
Autres conseils
Ces sortes de choses sont toujours très difficiles à faire. Vous aurez besoin de plusieurs requêtes pour chacun.
Alors, pour obtenir les joueurs juste avant et après votre position lorsque commandé par le score, tout d'abord, vous aurez besoin de comprendre ce que la position est. (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]
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])