ActiveRecordのモデルで集計テーブルの結果を扱う
通常のテーブルのモデルから、別のテーブルでの集計した結果をひもづけて取得したかったので、集計テーブルとモデルでJoinして、取得できるようにした。
集計テーブル取得用処理の作成
まず、集計テーブル取得用処理をUserのモデルに実装します。
集計部分は、ActiveRecord的に書く必要も特になかったので、SQL直で記述しています。joinした後の結果の取得時に対象の指定が必要なので、そこはselect
で対象の集計テーブルの名前を指定しておく。
def add_item_stats
item_stats = <<-SQL
(select
user_id,
count(case when is_public = 1 then 1 end) as public_item_count,
count(1) as all_item_count
from
items
group by user_id)
SQL
joins("left outer join #{item_stats} stats on users.id = stats.user_id").select('stats.*')
end
ActiveRecordのモデルからの利用方法
使用する際は、Userのモデルの取得先を指定した上で、使用します。
例えば、idが1のユーザーに対して、集計テーブルとjoinした結果を取得したい場合は、下記のように書きます。
user = User.select('users.*').where(id: 1).add_item_stats.first
実行されるSQLは下記のようになります。
> user = User.select('users.*').where(id: 1).add_item_stats.first
User Load (0.5ms) SELECT users.*, stats.* FROM `users` left outer join (select
user_id,
count(case when is_public = 1 then 1 end) as public_item_count,
count(1) as all_item_count
from
items
group by user_id)
stats on users.id = stats.user_id WHERE `users`.`id` = 1 ORDER BY `users`.`id` ASC LIMIT 1
取得した結果をモデルから結果を取得する場合は、通常のカラム同様、user.all_item_count
といった形でアクセスできるようになります。