SUM/MAX/MIN/AVG を GROUP BY の条件で使う

下記のような感じで記述する。

report_collection = ProductReport.aggregate(
  
   # grouping key
   :product_id,
   :date,

   # summary target
   :amount.sum,
   :tax.sum,
                              
   # condition
  :date => (start_date .. end_date)
)

# => [
#     [1, '2009-12-14', 100, 10],
#     [1, '2009-12-15', 200, 20],
#     [1, '2009-12-16',  58, 20],
#     [2, '2009-12-14', 511, 20],
#     [2, '2009-12-15',  85, 10],
# ]

集計対象の項目には :symbol に .sum/avg/count/max/min などのメソッドがあるので、それを呼び出した結果を指定する。これは、 :order とか不等号や NOT の指定と大体同じ。

一番よく理解できなかったのは、 grouping key の指定。最初は :group_by とかの特殊キーを指定するのかと思っていたが、これは上記の :product_id, :date のよう対象の項目を羅列するだけ。良く考えてみれば SQL を書くときも、 SELECT 句に書く項目と GROUP BY 句に書く項目って同じになることがほとんどなので、これは賢い指定方法だとおもった。

ちなみに、 GROUP BY の項目を明確に指定したい場合は、 :unique => true, :fields => [:product_id, :date] とか書くみたいだけど、あまり詳細に確認していない。


蛇足だけど、 :date の条件指定は上記のように Range オブジェクトを使うとわかりやすくていい。