我有一个展示位置表,可以跟踪每月的员工及其积分。
我正在努力弄清楚如何让员工在每个月都获得第一名。
我尝试过这样的事情
create_table "placements", :force => true do |t|
t.integer "employee_id"
t.date "month"
t.integer "points"
end
@previous_winners = @placements.includes(:employee).order('points DESC').first
我想我可能需要遍历所有月份?
答案 0 :(得分:1)
您可以使用group
按月对最高分进行分组。这样的事情应该有效:
@previous_winners = @placements.includes(:employee).group(:month).
order('points DESC').map(&:employee)
此查询返回每月包含关联员工的点数最高的展示位置,然后map函数会返回每条记录的员工。
此答案预先假定每个月的展示位置记录具有完全相同的日期
[编辑]
这个答案在postgres上根本不起作用,我认为它根本不会在MySQL上返回正确的结果!这是一个应该有效的小版本(但每个月都会运行数据库查询)
@previous_winners = @placements.distinct.pluck(:month).map do |month|
@placements.includes(:employee).where(:month => month).
order('points DESC').first.employee
end
Here是问题中描述的架构的SQL小提琴,如果有人想要玩它的话
答案 1 :(得分:1)
'GROUP BY'在PostgreSQL中的工作方式与在MySQL中的工作方式略有不同。您正在寻找的是以下SQL表达式的rails / ruby等效项:
SELECT DISTINCT ON (month) month,points, employee_id
FROM placements
order by month, points DESC
在rails控制器中,您可以使用以下方式获取上述内容:
@placements.select('DISTINCT ON (month) month, points, employee_id').where('YOUR_CONDITION').order('month, points DESC')
这只是一个关于如何在PostgreSQL中进行分组的示例,以满足您的需求。
PS:'DISTINCT ON'就是这里的诀窍:)。
答案 2 :(得分:0)
您可以使用类似的内容来获取上个月
from = Time.now.beginning_of_month - 1.month
to = from.end_of_month
然后您可以将它们添加到您的查询中。
@previous_winners = @placements.includes(:employee).where('month BETWEEN ? AND ?', from, to).order('points DESC').first