У меня есть приложения, в которых хранятся оценки игроков для каждого турнира. Так что у меня много-ко-многим ассоциации:SQL: Получить выбранный индекс строки из запроса
Tournament
has_many :participations, :order => 'rating desc'
has_many :players, :through => :participations
Participation
belongs_to :tournament
belongs_to :player
Player
has_many :participations
has_many :tournaments, :through => :participations
Модель Участие имеет rating
поле (поплавок), который хранит номинальное значение (это как баллами) для каждого игрока на каждом турнире.
То, что я хочу - получить последние 10 разрядов игрока (rank
- это позиция игрока на конкретном турнире, основанная на его рейтинге: чем больше рейтинг - тем выше рейтинг). На данный момент, чтобы получить звание игрока на турнир я загружаю все официальное участие на этот турнир, сортировать их по rating
полю и получить индекс участия игрока с кодом рубина:
class Participation < ActiveRecord::Base
belongs_to :player
belongs_to :tournament
def rank
tournament.participations.index(self)
end
end
Метода rank
участия получает свой родитель турнир, загружает все tournamentr официального участия в (заказанное rating desc
) и получить собственный индекс внутри этой коллекции
и затем что-то вроде:
player.participations.last.rank
одна вещь мне не нравится - ей нужно загружать все участие в турнире, и в случае, если мне нужны рейтинги игроков за последние 10 турниров, он загружает более 5 000 предметов (и его количество будет расти при добавлении новых игроков).
Я считаю, что должен быть способ использовать SQL для него. На самом деле я пытался использовать переменные SQL:
find_by_sql("select @row:[email protected]+1 `rank`, p.* from participations p, (SELECT @row:=0) r where(p.tournament_id = #{tournament_id}) order by rating desc limit 10;")
Этот запрос выбирает рейтинг 10 из данного турнира. Я пытался изменить его, чтобы выбрать последние 10 участия для данного пользователя и его ранга.
Поблагодарите любую помощь. (Я думаю, что решение будет запросом SQL, так как это довольно сложно для ActiveRecord).
P.S. Я использую rails3.0.0.beta4
UPD:
Вот окончательный запрос SQL, который получает последние 10 ряды игрока (кроме того, он загружает участие турниры, а)
SELECT *, (
SELECT COUNT(*) FROM participations AS p2
WHERE p2.tour_id = p1.tour_id AND p2.rating > p1.rating
) AS rank
FROM participations AS p1 LEFT JOIN tours ON tours.id = p1.tour_id WHERE p1.player_id = 68 ORDER BY tours.date desc LIMIT 10;
Спасибо, это полезно для меня :) –