2012-05-18 1 views
2

Итак, у меня есть таблица результатов для турнира, где могут встречаться несколько матчей с одним и тем же игроком.Rails 3 Sort Scope By Self-Accumulated Count

Таким образом, некоторые выборочные данные могут быть:

Результаты

Player_ID | Match_ID|Win|Elapsed_Time|etc.. 
1   | 1 |T | 1:00  |etc.. 
2   | 1 |F | 1:00  |etc.. 
1   | 2 |T | 3:00  |etc.. 
3   | 2 |F | 3:00  |etc.. 

Я хочу, чтобы подготовить рамки, которые будут рассчитывать поля Win, которые установлены Истина для каждого игрока и и группы по этому количеству поля ,

Так псевдо-код будет что-то вроде ...

область применения: most_wins,: все,: order_by => "Count (Wins игрока)"

Это даже возможно, или я должен повторно подумайте о моей структуре базы данных?

ответ

2

Прежде всего: Named Scopes Are Dead

Я предлагаю вам сделать следующее:

class Players < ActiveRecord::Base 
    .... 
    def self.with_win_count 
    #inner join if you want to filter out those who doesn't have any match, otherwise is should be left outer 
    joins("inner join (select Player_ID, count(Match_ID) as win_count from Results where Win = true group by Player_ID) t on (t.Player_ID = Player.ID)") 
    end 
end 

#somewhere in controller you would do 
best_players = Player.with_win_count.where("win_count > ?", [10]).order("win_count DESC") 

В случае, если вы хотите быть в таблице Результаты:

class Results < ActiveRecord::Base 
    .... 
    def self.with_win_count 
    joins("inner join (select Player_ID, count(Match_ID) as win_count from Results where Win = true group by Player_ID) t on (t.Player_ID = Results.Player_ID)") 
    end 
end 

это сработает, но я найти его немного уродливым.

И если вы хотите условное количество вложенного запроса простого способ будет:

class Players < ActiveRecord::Base 
    .... 
    def self.with_match_count(conditions) 
    #inner join if you want to filter out those who doesn't have any match, otherwise is should be left outer 
    joins("inner join (select Player_ID, count(Match_ID) as match_count from Results where #{conditions} group by Player_ID) t on (t.Player_ID = Player.ID)") 
    end 
end 
some_players = Player.with_match_count("Win = true").where("match_count > ?", [10]).order("match_count DESC") 

!!! Обратите внимание, что он подвержен SQL-инъекциям, если аргумент conditions будет построен непосредственно из пользовательского ввода.

+0

HI Forker, спасибо, что заполнили меня в области в Rails 3. Код, который вы предоставили, почти работает, но мне пришлось изменить def с_win_count на self.with_win_count, иначе он предоставит неопределенный метод для ошибки класса. – Noz

+0

ах, хороший! Благодаря! – forker

+0

Есть ли способ сохранить это в пределах только таблицы результатов? Причина, по которой я спрашиваю, заключается в том, что я использую это в динамическом запросе, который создается, и есть дополнительные поля из таблицы Results, которые я хотел бы фильтровать. Что-то вроде: 'query = Player.with_win_count.where (..........) query = query.where (results_field = ....) если условие' конечно, таблица Player является родительским результатом – Noz