Rails:左连接聚合计数 - 如何计算?

时间:2011-08-16 20:08:50

标签: sql ruby-on-rails-3 activerecord

在我的应用用户中注册属于事件。注册在注册模型中进行管理,该模型有一个名为“参加”的布尔字段。

我正在尝试生成排行榜并需要知道:每个用户的注册总数,以及每个单独事件流中用户注册的计数。

我正在尝试这个(在User.rb中):

# returns an array of users and their attendence count
def self.attendance_counts
    User.all( 
      :select => "users.*, sum(attended) as attendance_count", 
      :joins => 'left join `registrations` ON registrations.user_id = users.id', 
      :group => 'registrations.user_id', 
      :order => 'attendance_count DESC'
    )
end

当我在数据库中运行时,生成的SQL仅用于返回每个用户的总有人值,但返回的所有内容都是Rails中的用户记录。

我即将放弃并将每个流的counter_cache硬编码(它们相当固定)到User表中,只要注册模型保存上的有人参与属性发生更改,就会手动更新。

但是,我真的很好奇如何执行这样的查询。在计算有关系的记录的统计数据和报告时,它必须始终出现。

非常感谢您的时间和考虑。提前谢谢。

1 个答案:

答案 0 :(得分:6)

首先,作为样式和轨道功能的几点,可以帮助您构建数据库查询。

1)你最好把它写成范围而不是方法,即

scope attendance_counts, select("users.*, sum(attended) as attendance_count").joins(:registrations).group('registrations.user_id').order('attendance_count DESC')

2)最好不要在你构建的查询中调用all / find / first,直到你真正需要它(即在控制器或视图中)。这样,如果您决定在以后对数据库查询实施操作/片段缓存,则在向用户提供缓存的操作/片段时将不会调用它。

3)Rails有一系列功能来帮助聚合数据库数据。例如,如果您只想要用户的ID和有人参与的总和,您可以使用类似下面的代码:

Registrations.group(:user_id).sum(:attended)

其他功能包括countavgminimummaximum

最后,在回答您的问题时,rails将为您创建一个属性,以便您访问查询的选择部分中的任何自定义字段的值。 e.g。

@users = User.attendance_counts
@users[0].attendance_count # The attendance count for the first user returned by the query