Положение в рейтинге


У меня есть приложение Rails со следующими моделями:

  • пользователь
  • ставка

Пользователь имеет many_bets и ставки принадлежат Пользователю. Каждая ставка имеет значение Profitloss, которое указывает, сколько пользователь выиграл/проиграл на этой ставке.

Итак, чтобы вычислить, сколько конкретный пользователь выиграл в целом, я циклически перебираю его ставки следующим образом:

 User.bets.sum(:profitloss)

Я хотел бы показать пользователю его рейтинг по сравнению со всеми другими пользователями, который может выглядеть примерно так это:

"ваш общий рейтинг: 37-е место"

Для этого мне нужно суммировать общий выигрыш на одного пользователя и выяснить, в каком положении находится текущий пользователь.

Как это сделать и как это сделать, чтобы не перегружать сервер:)

Спасибо!

3 2

3 ответа:

Вы можете попробовать что-то похожее на

User.join(:bets).
    select("users.id, sum(bets.profitloss) as accumulated").
    group("users.id").
    order("accumulated DESC")

И затем найдите в полученном списке "пользователей" (не реальных пользователей, у них есть только два значимых атрибута, их ID и атрибут accumulated с суммой), соответствующий текущему.

В любом случае, чтобы получить позицию одного пользователя, вы должны вычислить позицию всех пользователей accumulated, но, по крайней мере, это только один запрос. Еще лучше, вы можете хранить в пользовательской модели накопленное значение и запрашивать только его для ранжирования.

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

Добавьте столбец position в модель User, получите список всех пользователей, вычислите их глобальный profitloss, отсортируйте список пользователей с их profitloss и, наконец, обновите атрибут position каждого User с их позицией в списке.

Лучший способ сделать это-сохранить предварительно вычисленный итог в вашей базе данных либо на самой модели user, либо на отдельной модели, которая имеет отношение 1:1 к user. Если вы этого не сделаете, вам придется вычислить сумму для всех пользователей в любое время, чтобы получить их рейтинг, что означает полную работу таблицы с таблицей bets. Тем не менее, этот запрос даст вам желаемые результаты, если более чем 1 человек имеет тот же итог, он будет засчитан как рейтинг X:

select id, (select count(h.id) from users u inner join 
(select user_id, sum(profitloss) as `total` from bets group by user_id) b2
on b2.user_id = u.id, (select id from users) h inner join
(select user_id, sum(profitloss) as `total` from bets group by user_id) b 
on b.user_id = h.id where u.id = 1 and (b.total > b2.total)) 
as `rating` from users where id = 1;

Вам нужно будет подключить user.id к запрос в where id = X

Если вы добавляете столбец в таблицу user, чтобы отслеживать их общее количество, запрос немного проще, в этом примере имя столбца total_profit_loss:

select id, total_profit_loss, (select count(h.username)+1 from users u, 
(select username, score from users) h 
where id = 1 and (h.total_profit_loss > u.total_profit_loss)) 
as `rating` from users where id = 1;