【问题标题】:Rails - How to avoid multiple querys on thisRails - 如何避免对此进行多次查询
【发布时间】:2012-02-16 15:35:01
【问题描述】:

我有这组表(我正在使用 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申请assignment1、assignment2、assignment3如下:

                        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

假设我想在 TODAY 搜索用户作业的最接近 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 问题)

【问题讨论】:

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


    【解决方案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 => "id NOT IN (#{@au.collect(&:user_id}) 完成 -那么这个解决方案不合适,如果是这样的话,那么我认为你可能已经在做最好的方法了,虽然我会把你的方法改成范围 - 如果你想让我告诉你它的样子让我知道。

    【讨论】:

    • 打错了应该是u.last_date :)
    • 我试过了,我得到一个错误 PGError: ERROR: sintax error near «LEFT» LINE 6: LEFT JOIN users.id = assignment_users.user_id A... ^ : SELECT users.*, assignment_users. user_id, assignment_users.assignment_id, (SELECT id as last_assignment_id, date as last_date FROM assignmenttments WHERE date
    • 以上答案因反馈而改变
    • 其实日期列在 assignments 表上,如何修改?
    • 第 2 行:MAX(assignment_users.date) => MAX(assignments.date)
    猜你喜欢
    • 1970-01-01
    • 2016-01-23
    • 2022-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-28
    • 2015-02-16
    • 1970-01-01
    相关资源
    最近更新 更多