1

我有一个Users模型has_many EventLogs

我想创建一个范围,该范围将按照他们拥有的 EventLogs 出现次数最多的用户进行排序。

scope :highest_completed_events, .....

如何计算状态为 2 的 EventLogs 的数量,然后对此类事件发生率最高的用户进行排序。

User.joins(:event_logs).where("event_logs.status_id = 2")#... COUNT, then ORDER BY

希望这是有道理的。

4

2 回答 2

3

您可以执行以下查询,以让您的用户按他们拥有的事件数排序:

@users = User.
  select("users.*, COUNT(event_logs.id) as event_logs_count").
  joins('LEFT JOIN event_logs ON event_logs.user_id = users.id').
  group('users.id').
  order('event_logs_count DESC')

您应该使用 a LEFT JOIN,因为您希望包括没有任何事件的用户。

如果您要将其编写为范围:

scope(:highest_completed_events, {
  select: 'users.*, COUNT(event_logs.id) as event_logs_count',
  joins: 'LEFT JOIN event_logs ON event_logs.user_id = users.id',
  group: 'users.id',
  order: 'event_logs_count DESC'
})

@users = User.highest_completed_events

为了按特定状态过滤事件,只需使用where().

@users = User.
  select("users.*, COUNT(event_logs.id) as event_logs_count").
  joins('LEFT JOIN event_logs ON event_logs.user_id = users.id').
  where('event_logs.status = ?', STATUS_COMPLETE).
  group('users.id').
  order('event_logs_count DESC')

顺便说一句,有时您会遇到 ActiveRecordselect()在执行类似@users.count. 我通常做的是将这种事情嵌套在自定义from()语句中。

_from = User.
  select("users.*, COUNT(event_logs.id) as event_logs_count").
  joins('LEFT JOIN event_logs ON event_logs.user_id = users.id').
  group('users.id').
  order('event_logs_count DESC').to_sql

@users = User.from("(#{_from}) as users")

@users.count # will work
于 2013-11-03T17:01:52.320 回答
1

尝试:

User.all.sort_by{|u| u.event_logs.select{|l| l.status_id = 2}.count}.reverse

还是“事件日志”?你的线路不应该是has_many :event_logs吗?

顺便说一句,我的解决方案效率不高,但与数据库无关。

于 2013-11-03T17:15:41.260 回答