2010-01-26 1 views
3

У меня есть огромный список ранжированных по различным значениям (например, баллы.)Рейтинг в Django ORM или SQL?

Так я хватаю список заказанного этих значений:

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

Я хотел бы:

  • Возьмите игрока и получите соседних игроков

P1 оценка: 123

P2 оценка: 122

ВАС! оценка:

P3 оценка: 90

P2 оценка: 89

  • захватить положение!

Вы ранг # 1234 для очков

Вы ранжируются # 9876 для кармы


Помощь будет очень высоко ценится. спасибо :)

ответ

1

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

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

+1

'RANK()' похоже, является расширением SQL Server. Он недоступен в большинстве диалектов SQL. –

+0

Спасибо, удивительный ответ! Btw @ Daniel не может найти RANK() в MySQL-ссылке, скажете ли вы, что диалект MySQL поддерживает это? – RadiantHex

+1

Это не только SQL Server; Postgres 8.4 включает RANK(). Не знаю о MySQL; По-моему, по крайней мере, у него что-то похожее. –

8

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

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

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

спасибо Даниилу. Это очень полезный ответ! – RadiantHex

+1

- вам не нужно все(), просто примените фильтр - score__lt работает лучше для ранжирования (равный балл -> равный ранг) - в последней части результат не упорядочен, поэтому позиция не поможет, вы должен сначала заказать - если позиция <2, будет исключение, вы должны закрепить минимум положения-2 до 0 (высокая часть в порядке) –

0

Я сделал это с 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]) 

 Смежные вопросы

  • Нет связанных вопросов^_^