使用Ruby 1.9.2, Rails 3.1。我有以下代码:
# review.rb
def calculate_rating(reviewable)
total_rating = Review.select("rating").where(:reviewable_id => self.reviewable_id)
sum_rating = total_rating.sum(:rating)
new_rating_average = sum_rating.to_f / total_rating.size
reviewable.update_attribute(:rating_average, new_rating_average)
end
total_rating
实际用于获得返回的评级数的总数,而sum_rating
用于将每个total_rating
相加。我注意到我的查询要运行多次才能得到结果。
是否有任何方法重构它来提高性能?
谢谢。
活动记录api公开SQL平均函数,因此您应该能够执行
average_rating = Review.where(:reviewable_id => self.reviewable_id).average(:rating)
一般情况下,您可能需要编写自定义sql,例如,如果平均函数不存在,您可以编写
select count(*) as c, sum(rating) as total from ratings where ( ... )
如果你想在不同的条件下计算多个事物,你可以使用像
这样的东西select count(*) as number_of_ratings, SUM(IF(rating > 5, 1, 0)) as number_of_ratings_greater_than_5, SUM(rating) as total_score
获取,在1查询评分的个数,它们的和和评分的个数> 5。不过要谨慎使用,你不会想用一个非常慢的查询代替2个快速查询!
假设reviewable有很多评论:
reviewable.update_attribute :rating_average, reviewable.reviews.average(:rating)
或者,如果您的数据库支持语法[1]
Reviewable.connection.execute <<-eos
UPDATE reviewable SET (rating_average) = ((
SELECT avg(rating) FROM review WHERE reviewable_id = {reviewable_id}
)) where id = {reviewable_id}
eos
[1] http://publib.boulder.ibm.com/infocenter/idshelp/v10/index.jsp?topic=/com.ibm.sqls.doc/sqls875.htm