Sql Rails使用相关表中的数据进行查找和排序

Sql Rails使用相关表中的数据进行查找和排序,sql,ruby-on-rails,ruby,Sql,Ruby On Rails,Ruby,我关联了两个模型业务和评级。一个企业可以被评级多次,每个评级存储一个0到5的整数 我想创建一个“名人堂”页面,通过根据平均评级(使用评级模型)对企业进行排序,并将结果限制在10个,我在其中列出了前10家企业 我不知道如何为控制器编写hall\u of \u fame方法,或者我还需要一个助手吗?假设您有一个has\u many并且属于两个模型之间的关系,您可以尝试使用Rails支持的(非常方便的)MySQL GROUP BY子句: @hall_of_fame = Business.find(

我关联了两个模型
业务
评级
。一个企业可以被评级多次,每个评级存储一个0到5的整数

我想创建一个“名人堂”页面,通过根据平均评级(使用
评级
模型)对企业进行排序,并将结果限制在10个,我在其中列出了前10家企业


我不知道如何为控制器编写hall\u of \u fame方法,或者我还需要一个助手吗?

假设您有一个has\u many并且属于两个模型之间的关系,您可以尝试使用Rails支持的(非常方便的)MySQL GROUP BY子句:

@hall_of_fame = Business.find(
                               :all, 
                               :joins => :ratings, 
                               :group => 'business_id', 
                               :order => 'AVG(ratings.rating) DESC', 
                               :limit => 10
                             )
如果要添加平均评级,可以将其包含在:select参数中,例如:

@hall_of_fame = Business.find(
                               :all,
                               :select => 'businesses.name, AVG(ratings.rating)'
                               :joins  => :ratings, 
                               :group  => 'business_id', 
                               :order  => 'AVG(ratings.rating) DESC', 
                               :limit  => 10
                             )
当然,如果表之间没有冲突的列名,您可以安全地从:select和:order参数中删除前导的“business.”和“ratings.”


您可能希望在模型中使用此代码创建一个方法,而不是在控制器中使用此代码,但这取决于您。

在控制器中,您可以使用类似于以下内容的内容获取前十大业务:

top10 = Business.average('ratings.rating', :joins => 'INNER JOIN ratings ON businesses.id = ratings.business_id', :group => 'businesses.id', :order => 'avg_ratings_rating DESC', :limit => 10 )

# example of using results of above line
top10.each { |id, avg| puts Business.find(id).name + " score: " + avg.to_s }
您可以编写
:order=>'avg(ratings.rating)
,而不是
:order=>'avg(ratings.rating)
。因此,它将返回一个有序散列。当你迭代它时,你会得到你想要的

可能更好的方法是向业务模型中添加一个类方法,如下所示:

def self.getTop10
  average('ratings.rating', :joins => 'INNER JOIN ratings ON businesses.id = ratings.business_id', :group => 'businesses.id', :order => 'avg_ratings_rating DESC', :limit => 10 )
end
然后在控制器中,您可以执行以下操作:

top10 = Business.getTop10

您可以使用:having选项指定阈值。非常感谢!正是我需要的。