読者です 読者をやめる 読者になる 読者になる

ActiveRecordで集計関数の結果を複数selectしたいんです

select sum(min_salary), sum(max_salary) from jobs;

これをActiveRecordで書きたい。

ベタに書くと

rec = Job.select(<<-SELECT).all[0]
  SUM(MIN_SALARY) AS MIN_SALARY
  ,SUM(MAX_SALARY) AS MAX_SALARY
SELECT
# => SELECT SUM(MIN_SALARY) AS MIN_SALARY
# ,SUM(MAX_SALARY) AS MAX_SALARY
# FROM "JOBS"

p rec.min_salary # => 124888
p rec.max_salary # => 251088

こうなる。

関係ないけど、仕事中にActiveRecordの書き方で詰まったら、諦めて直接SQL書いた方が早いよね。閑話休題。

こう書けそうだけど、これは無理。

Job.sum(:min_salary, :max_salary)
Job.sum([:min_salary, :max_salary])
Job.sum(:min_salary).sum(:max_salary)

残念です。。

Arelを利用してこう書くのです。

j = Job.arel_table
rec = Job.select([j[:min_salary].sum.as('min_salary'), j[:max_salary].sum.as('max_salary')]).all[0]
# => SELECT SUM("JOBS"."MIN_SALARY") AS min_salary, SUM("JOBS"."MAX_SALARY") AS max_salary FROM "JOBS"

p rec.min_salary # => 124888
p rec.max_salary # => 251088

列別名もちゃんと使えます。

rec = Job.select([j[:min_salary].sum.as('sum_min'), j[:max_salary].sum.as('sum_max')]).all[0]
# => SELECT SUM("JOBS"."MIN_SALARY") AS sum_min, SUM("JOBS"."MAX_SALARY") AS sum_max FROM "JOBS"
p rec.sum_min # => 124888
p rec.sum_max # => 251088

(^ω^)にこっ

参考

2個目のslideshareはあとで全部見て試してみようと思う。これを把握できればArelは概ねOKなんじゃないかな。。