ActiveRecord查询详细信息和摘要数据

时间:2010-11-09 19:40:22

标签: sql ruby-on-rails activerecord

使用Rails3,我有一个downloads表,其中包含download_datecredits列。我想要生成的是如下表:

 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上运行。

我希望我已经提供了有关问题域和所涉问题的充分信息。有什么意见或建议吗?

2 个答案:

答案 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