6

我有这个Event模型

class Event < ActiveRecord::Base
  attr_accessible :starts_at, :ends_at, :price
end

AnEvent可以是单个即时事件:

Event.create(:starts_at => Date.today, :ends_at=>nil, :price => 10.0)

它也可以跨越数天或数月:

Event.create(:starts_at => Date.today, :ends_at => (Date.today + 2.months), :price => 20.0)

我想按月分解事件的成本,因此即时事件的成本自然会落入它所属的月份,而跨越多个月的事件的成本应该在这些月份之间按比例分配。

显然这很难使用 SQL 来处理,但也许有人对此有一些建议?

计算这种聚合的最有效方法是什么?

更新:

这是 sqlfiddle 上数据的明确定义的结构:http ://sqlfiddle.com/#!12/a532e/6

我想从这个数据集中得到类似的东西:

( (Date('2013-01-01'), 31.6), (Date('2013-02-01'), 8.4) )
4

1 回答 1

3
SELECT event_id
      ,date_trunc('month', day)::date AS month
      ,sum(daily) AS price_this_month
FROM  (
   SELECT event_id
         ,generate_series(starts_at
                         ,COALESCE(ends_at, starts_at)
                         ,interval '1 day') AS day
         ,price / COALESCE((ends_at - starts_at) + 1, 1) AS daily
   FROM   events
   ) a
GROUP  BY 1,2
ORDER  BY 1,2;

-> sqlfiddle

我为 PostgreSQL 提供了一个更新的 sqlfiddle。您的原件似乎是用于 MySQL 的。

诀窍是:

  • 用于generate_series()每天为每个事件创建一行。
  • 用于COALESCE处理NULL似乎被允许的值ends_at
  • daily通过将价格除以之间的天数来计算成本,starts_atends_at + 1通过一个来修复。在 的情况下默认为 1 ends_at IS NULL
  • 按事件和月份重新汇总。

瞧。

您甚至可以获得每月的准确费率,具体取决于每月有多少天。2 月(28 天)比 1 月(31 天)便宜。

于 2013-01-10T23:46:31.610 回答