Ранжирование в Django ORM или SQL? - PullRequest
5 голосов
/ 26 января 2010

У меня огромный список, ранжированный по различным значениям (например, оценки)

Поэтому я беру список, упорядоченный по этим значениям:

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

Я бы хотел:

  • Захватите игрока и получите соседних игроков

P1 оценка: 123

P2 оценка: 122

ВЫ ! счет: 110

P3 оценка: 90

P2 оценка: 89

  • Захватите позицию !

Вы оценивались # 1234 по результату

Вы ранжированы # 9876 за карму


Помощь была бы очень признательна. спасибо:)

Ответы [ 3 ]

9 голосов
/ 26 января 2010

Подобные вещи всегда очень трудно сделать. Вам потребуется несколько запросов для каждого.

Итак, чтобы получить игроков до и после вашей позиции, когда они упорядочены по счету, сначала вам нужно выяснить, что это за позиция. (Обратите внимание, что это предполагает, что вы не можете иметь более одного человека с одинаковым счетом, что не обязательно может быть правдой.)

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]
1 голос
/ 26 января 2010

Чтобы получить рейтинг пользователя:

(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 

Где id_of_user - параметр, содержащий идентификатор текущего игрока. Чтобы получить соседних игроков и текущего пользователя:

(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;

Где player_ranking - это рейтинг, полученный из запроса выше.

Надеюсь, это поможет!

Обновление : MySQL не имеет функции rank () (в MS SQL, Oracle, Postgres есть такая функция). Я посмотрел вокруг и получил эту ссылку, объясняющую, как сделать ранжирование в MySQL: http://www.artfulsoftware.com/infotree/queries.php?&bw=1024#460.

0 голосов
/ 22 июня 2015

Я сделал это с 3 запросами в ORM, но я думаю, что меньшее количество запросов будет лучше:

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])
...