1

每个User都有很多Purchases。我想找到前 28 天中每一天的总和。

t1 = Time.now - (28.days)
t2 = Time.now
@dailysum = Array.new(29)
(0..29).each do |i|
  @dailysum[i] = @user.purchases.where(:created_at => (Time.now-(i.day))..(Time.now-((i-1).days))).sum(:amount)
end

这行得通,但我确信有更好的方法来解决这个问题。有什么建议么?

4

3 回答 3

2

您需要传递一个:group选项来求和。该:group选项的值因您的数据库而异。我将提供一个 pg 和 mysql 版本。

# purchases.rb
def self.recent(num)
  where('created_at > ?', num.days.ago
end

# PG version
@user.purchases.recent.sum(:amount, group: "DATE_PART('year', purchases.created_at) || '-' || DATE_PART('month', purchases.created_at) || '-' || DATE_PART('day', purchases.created_at)")

# mysql version
@user.purchases.recent.sum(:amount, group: "DATE(purchases.created_at)")

这将产生一个哈希,其中键是日期,值是购买的总和。

与过去 28 天内每天的查询相比,这将减少 27 个查询

于 2013-02-06T10:58:45.430 回答
2

/!\ 查看我的另一个(更好的)答案

此答案将计算过去 28 天的购买总额

阅读我的其他答案以计算过去 28 天的总和。

我为那些可能对此感兴趣的人保留了这个在线。


@user.purchases
    .where('created_at > ?', 28.days.ago) # retrieve all purchases within the last 28 days
    .sum(:amount)                         # get the sum of the amount column

如果您想使用@andy 建议的范围:

# in purchase.rb
scope :recent, ->(d) { where('created_at > ?', d.days.ago) }

# then in you controller
@user.purchases
  .recent(28)          # retrieve all purchases within the last 28 days
  .sum(:amount)        # get the sum of the amount column
于 2013-02-06T11:14:51.940 回答
0

现在我已经更好地理解了这个问题,这是第二次尝试。

脱离上下文很难做到这一点。

user.purchases
  .where('created_at > ?', 28.days.ago)
  .group_by { |p| p.created_at.to_date }
  .collect { |d, ps| [d, ps.sum { |p| p.amount }]  }

这应该返回一个数组数组,其中包含每个日期和该日期的金额总和:

[
  ["Mon, 28 Jan 2013", 137],
  ["Tue, 29 Jan 2013", 49]
  ["Wed, 30 Jan 2013", 237]
]
于 2013-02-06T14:20:55.820 回答