使用Rails3,我有一个downloads
表,其中包含download_date
和credits
列。我想要生成的是如下表:
Date Credits
2010-11-01 25
2010-11-01 27
*2010-11-01 52 <= Sum of previous 2 rows
2010-11-02 32
*2010-11-02 32 <= Sum of previous row
这可以通过以下方式实现:
u.downloads.group_by(&:download_date).each do |date, downloads|
downloads.each do |d|
puts " %10s %3d" % [d.download_date, d.credits]
end
puts "*%10s %3d" % [date, downloads.sum(&:credits)]
end
这个解决方案虽然有效,但它不像Rails那样,导致发出相当多的SQL查询。假设100个用户每年下载x 10,000次,并且每年结束时的查询次数为每个服务页面的1,000,000个。
如果可能的话,我提出的任何解决方案都应该与数据库无关。我知道我将在Heroku上使用PostgreSQL进行部署,而我的开发版本,无论多么被误导,仍在MySQL上运行。
我希望我已经提供了有关问题域和所涉问题的充分信息。有什么意见或建议吗?
答案 0 :(得分:1)
你正在做的事实上已经非常优化了。唯一的问题 - 您一次只能下载一个。使用u.downloads.all.group_by
(在其中添加all
)以便一次加载所有下载。通过这种方式,您可以完成一个查询。
更新:虽然在第二眼看来,在Rails 3中,这甚至不应该产生多个查询。您可能遇到N + 1问题的原因有很多。例如,如果从视图中某处的某个关联对象反向引用特定下载 - rails可能不知道此下载已作为数组的一部分从数据库中获取,并再次重新获取它。如果您看到许多查询 - 此代码不应该导致它们。
答案 1 :(得分:0)
由于您自己已经在执行迭代,因此您也可以执行以下操作:
u.downloads.group_by(&:download_date).each do |date, downloads|
subtotal_credits = 0
downloads.each do |d|
puts " %10s %3d" % [d.download_date, subtotal_credits += d.credits]
end
puts "*%10s %3d" % [date, subtotal_credits]
end