6

私はこのEventモデルを持っています

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

Eventは、単一のインスタント イベントにすることができます。

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()イベントごとに 1 日 1 行を作成するために使用します。
  • で許可されているように見える値COALESCEを処理するために使用します。NULLends_at
  • 価格をとdailyの間の日数で割ってコストを計算し、オフバイ 1 を修正します。の場合、デフォルトは 1 です。starts_atends_at + 1ends_at IS NULL
  • イベントごと、月ごとに再集計します。

出来上がり。

1 か月の日数に応じて、1 か月あたりの正確な料金も取得できます。2 月 (28 日) は 1 月 (31 日) よりも安いです。

于 2013-01-10T23:46:31.610 に答える