我有以下模型结构:嘉年华有许多活动,有很多竞争对手。竞争对手有多态参与者,可以是学生,也可以是团队(有很多学生)。在代码中:
class Carnival < ActiveRecord::Base
has_many :events
end
class Event < ActiveRecord::Base
belongs_to :event_type
belongs_to :division
has_and_belongs_to_many :genders
has_and_belongs_to_many :grades
has_many :competitors
has_many :students, through: :competitors, :source => :participant, :source_type => 'Student'
belongs_to :carnival
end
class Competitor < ActiveRecord::Base
belongs_to :event
belongs_to :participant, polymorphic: true
belongs_to :grade
belongs_to :house
end
class Team < ActiveRecord::Base
has_one :competitor, :as => :participant
has_one :event, :through => :competitor
has_and_belongs_to_many :students
end
class Student < ActiveRecord::Base
belongs_to :grade
belongs_to :house
belongs_to :gender
has_many :competitors, :as => :participant
has_many :events, :through => :competitors
has_many :carnivals, :through => :events
has_and_belongs_to_many :teams
end
竞争对手有一个分数属性,因此在运行事件后,会为其分配分数。
我想要的是一系列方法,可以让我所有学生的总分。
Student.with_total_points_for_carnival(c)
Student.with_individual_points_for_carnival(c)
Student.with_team_points_for_carnival(c)
我得到了一些可以提高总分的SQL(虽然我对它如何正常工作有点不舒服,因为我只是偶然发现它):
SELECT
name,
SUM(points) as points
FROM
public.students_teams,
public.students,
public.teams,
public.competitors,
public.events
WHERE
students_teams.team_id = teams.id AND
students.id = students_teams.student_id AND
competitors.participant_id = teams.id AND
events.id = competitors.event_id AND
carnival_id = 1
GROUP BY
public.students.id
ORDER BY
points DESC
这给出了总积分。我的Rails尝试给了我结果,但它们不正确,它们也不是学生记录:
def self.with_total_points_for(carnival)
Student.
joins(:competitors, :events, teams: { competitor: :event}).
where('events.carnival_id = ?', [carnival.id]).
group('students.id').
sum('competitors.points')
end
有关如何使其正常工作的任何指导?所以我可以去:
<% Student.with_total_points_for(@carnival).each do |s| %>
<%= s.name %>: <%= s.total_points %> <br>
<% end %>
更好的是像Student.with_all_points_for
这样的功能或范围让我这样做:
<% Student.with_all_points_for(@carnival).each do |s| %>
<%= s.name %>: <%= s.total_points %> / <%= s.individual_points %> / <%= s.team_points %> <br>
<% end %>
但现在宝贝步骤......
答案 0 :(得分:0)
我不确定我是否正确地抓住了你的目标,但我认为这可能对你有帮助
将所需字段添加到select
def self.with_total_points_for(carnival)
Student.
joins(:competitors, :events, teams: { competitor: :event}).
where('events.carnival_id = ?', [carnival.id]).
group('students.id').
select('students.*, SUM(competitors.points) AS total_points')
end
一些注意事项:
students.*
,您应该直接列出所有需要的列:select('students.id, students.name, ..., total_points')
select
列出所涉及的表格中的任何列,但请记住您在查询中使用group
PS我不确定在一个简单的查询中有一种简单的方法可以获得individual_points
和team_points
。我认为你应该使用子查询来实现这个目的,并将它们插入到主查询中。要小心,因为它可能是对DB的重要请求,并且需要进行优化。