Ranking innerhalb Django ORM oder SQL?
-
22-09-2019 - |
Frage
Ich habe eine riesige Liste von verschiedenen Werten gewählt (z. B. Partituren)
Also habe ich die Liste greifen durch diese Werte bestellt:
players = Player.objects.order_by('-score', '-karma')
Ich möchte:
- Schnappen Sie sich ein Spieler und nutzen Sie die Nachbar Spieler
P1 Punktzahl: 123
P2 Punktzahl: 122
! Score: 110
P3-Score: 90
P2-Score: 89
- Ergreifen Sie die Position
Sie sind # 1234 für Punktzahl auf Platz
Du # 9876 für Karma gewählt
Hilfe sehr geschätzt würde. Dank:)
Lösung
Die Rangliste des Benutzers zu erhalten:
(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
Wo id_of_user ist der Parameter die ID des Spielers enthält. Um den Nachbarn Spieler zu erhalten und der aktuelle Benutzer:
(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;
Wo player_ranking wird die aus der Abfrage erhalten Ranking oben.
Hope, es hilft!
Aktualisieren : MySQL hat keinen Rang () Funktion (MS SQL, Oracle, Postgres hat). Ich sah mich um und ich habe diesen Link zu erklären, wie in MySQL zu tun Ranking: http://www.artfulsoftware.com/infotree/queries.php?&bw=1024#460 .
Andere Tipps
Diese Art von Dingen ist immer sehr schwer zu tun. Sie werden für jeden mehrere Abfragen benötigen.
Also, um die Spieler zu bekommen kurz vor und nach Ihrer Position, wenn sie von dem Punktwert sortiert, zuerst müssen Sie arbeiten heraus, was diese Position ist. (Beachten Sie, dass dies setzt voraus, dass Sie nicht mehr als eine Person mit dem gleichen Ergebnis haben können, die nicht unbedingt wahr sein können.)
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]
Ich tat dies mit 3 Abfragen mit ORM, aber ich denke, weniger von Anfragen zählen besser wäre:
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])