巨大なカートを持っている場合、使用するMAX
と遅くなる可能性があります。GROUP BY
私はこのアプローチを使用します。
nq = Cart.where("carts.user_id = users.id AND carts.purchased_at >= ?", 3.months.ago)
User.where("NOT EXISTS (#{nq.to_sql})")
last_purchase_at
さらに良いことに、モデルに呼び出される列を追加してUser
、このクエリを効率的にします。
class User
# add a new column called last_purchase_at
# index the last_purchase_at column
def self.dormant_users(period=3.months)
User.where("last_purchase_at <= ?", period.ago)
end
end
モデルに after_create コールバックを追加して、Cart
モデルを更新しUser
ます。
class Cart
after_create :update_user_last_purchase_at
def update_user_last_purchase_at
user.update_attribute(:last_purchase_at, purchased_at)
end
end
このコードを移行スクリプトに追加してlast_purchase_at
、既存のUser
モデルの列を設定します。
User.connection.execute("
UPDATE users
JOIN (
SELECT a.user_id, MAX(a.purchased_at) purchased_at
FROM carts a
GROUP BY a.user_id
) carts ON carts.user_id= users.id
SET users.last_purchase_at = cards.purchased_at")
これで、休止中のユーザーを次のように取得できます。
User.dormant_users # dormant for last 6 months
User.dormant_users(6.months) # dormant for last 6 months