Rails - 如何避免对此进行多次查询

时间:2012-02-16 15:35:02

标签: sql ruby-on-rails ruby-on-rails-3 postgresql ruby-on-rails-3.1

我有这组表(我正在使用postgresql)

User (with id, first_name, ....)
Assignment (with id, name, start_date, finish_date,....)
AssignmentUser(with assignment_id, user_id, flag_status)

flag_status是一个布尔值,表示用户是否仍在分配中。

假设user1申请赋值1,赋值2,赋值3如下:

                        start_date     finish_date   flag_status
user1  assignment1      11-11-11       11-12-11      false
user1  assignment2      01-10-11       01-02-12      true
user1  assignment3      01-01-12       01-03-12      true

假设我想在今天搜索用户作业的最近start_date。

我在我的用户模型中完成了这个:

  def last_date
    self.assignments.where("date < ?", Date.today).max.try(:date)
  end

和这个

def last_status
  AssignmentUser.find_by_assignment_id_and_user_id(Assignment.find_by_date(self.last_date), self.id).flag_status if self.last_date.present?
end

在我看来为每个用户:

User.all.each do |u|
  <td>   u.first_name   </td>
  <td>   u.last_date   </td>
  <td>   u.last_status  </td>
end

它运行良好但是,在我的日志中,我看到每个用户有3个查询(正如预期的那样)。 所以我的问题是:我怎样才能避免这些多次查询? (我猜这更像是一个SQL问题,而不是一个Rails)

1 个答案:

答案 0 :(得分:1)

@au = AssignmentUsers.find_by_sql(
  "SELECT assignment_users.user_id, MAX(assignment_users.date) as last_date,
   assignment_id, 
   assignments.flag_status,
   users.first_name
  FROM assignment_users
  LEFT JOIN assignments
   ON assignments.id = assignment_id
  LEFT JOIN users
   ON users.id = user_id
  WHERE date < CURDATE()
  GROUP BY user_id;"
 )

然后在你看来:

@au.each do |u|
 <tr>
   <td>   u.first_name   </td>
   <td>   u.last_date    </td>
   <td>   u.last_status  </td>
 </tr>
end

请注意:这是在AssignmentUsers上进行迭代,因此如果有任何用户没有分配,他们将被遗漏。如果不够好(即你不想撤回第二个列表 - 很容易通过User.all完成(:conditions =&gt;“id not IN(#{@ au.collect(&amp;:user_id)} ) - 那么这个解决方案是不合适的,如果是这样,那么我认为你可能已经做到了最好的方式,虽然我会把你的方法改成范围 - 如果你想让我告诉你它会是什么样子让我知道。