Ranking dentro del ORM de Django o SQL?
-
22-09-2019 - |
Pregunta
Tengo una lista enorme clasificado por diversos valores (por ejemplo. Puntajes)
Así que agarrar la lista ordenada por estos valores:
players = Player.objects.order_by('-score', '-karma')
Me gustaría:
- Tome un jugador y obtener los jugadores vecinos
puntuación P1: 123
puntuación P2: 122
! anotar: 110
puntuación P3: 90
puntuación P2: 89
- Coge la Posición
se clasificó # 1234 para la puntuación
se clasificó # 9876 para el karma
La ayuda sería muy apreciada. Gracias:)
Solución
Para obtener el rango del usuario:
(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
Cuando id_of_user es el parámetro que contiene el id del jugador actual. Para conseguir que los jugadores vecinos y el usuario actual:
(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;
Donde player_ranking está el ranking obtiene a partir de la consulta anterior.
Hope que ayuda!
Actualizar : MySQL no tiene una función de rango () (MS SQL, Oracle, Postgres tiene uno). Miré a mi alrededor y me dieron este enlace que explica cómo hacer la clasificación en MySQL: http://www.artfulsoftware.com/infotree/queries.php?&bw=1024#460 .
Otros consejos
Este tipo de cosas son siempre muy difícil de hacer. Usted necesitará varias consultas para cada uno.
Así que, para conseguir que los jugadores justo antes y después de su posición cuando es ordenado por puntuación, primero tendrá que trabajar en lo que es la posición. (Tenga en cuenta que esto supone que no se puede tener más de una persona con la misma puntuación, que puede no ser necesariamente cierto.)
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]
Lo hice con 3 consultas con ORM, pero creo que menos cuenta de las consultas sería mejor:
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])