はじめに
Railsで合計値もとめる場合にsum
を利用すると思います。
やりたかったことは本の金額に税率をかけて税込価格を求めたかったのですが、AS
を使って別名をつけたときにうまくいきませんでした。
2.4.1 :027 > Book.select("id, ROUND(price * 1.08) AS price_in_tax").sum('price_in_tax')
(2.4ms) SELECT SUM(price_in_tax) FROM "books"
ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: price_in_tax: SELECT SUM(price_in_tax) FROM "books"
from (irb):27
SQLを見てみるとそりゃそうかって感じですよね。
前準備
Bookモデル
Bookモデルには値段(price
)カラムを持っています。
class CreateBooks < ActiveRecord::Migration[5.2]
def change
create_table :books do |t|
t.integer :price
t.timestamps
end
end
end
seedデータ
Book.create!(price: 255)
Book.create!(price: 100)
Book.create!(price: 50)
Book.create!(price: 10)
Book.create!(price: 30)
Book.create!(price: 120)
Book.create!(price: 150)
Book.create!(price: 250)
Book.create!(price: 135)
Book.create!(price: 300)
Arelを使うといいらしい
Arelを使うとSQLを自在に組み立てて実行することができそうです。
そのオブジェクトをfrom
で指定することで、普段の?ActiveRecordのメソッドを実行できます。
table = Book.select("id, ROUND(price * 1.08) AS price_in_tax").arel
Book.from(table).sum(:price_in_tax) # 1512.0
SQLは次のように組み立てられていました。サブクエリみたいな扱いになっているんですね。
SELECT SUM(price_in_tax) FROM (SELECT id, ROUND(price * 1.08) AS price_in_tax FROM "books")
*追記(2019/03/26)
arel
を使わなくても同じ結果になるようですね
table = Book.select("id, ROUND(price * 1.08) AS price_in_tax")
Book.from(table).sum(:price_in_tax) # 1512.0
組み立てられたSQLはこんな感じです。
SELECT SUM(price_in_tax) FROM (SELECT id, ROUND(price * 1.08) AS price_in_tax FROM "books") subquery
そもそもさ。。。
合計値を求めてから税率を求めてもいいですよね
税込価格だけじゃなく、AS
を使って別名を付けて合算するなんてことはよくあるのでいいサンプルじゃないかもしれないですね
Book.sum(:price) * 1.08 # 1512.0
おわりに
Arelを使ってSQLを自由自在に組み立ててる記事はいっぱいあるのですが、それを実行した結果はあまり見なかったので誰かの助けになれば幸いです