Rails中的复杂连接查询

时间:2009-08-14 21:58:40

标签: sql ruby-on-rails join

我有3个表 - 场地,用户和更新(有一个整数用于评级) - 我想写一个查询,它将返回我所有场地的列表以及仅使用最新版本的平均评分更新每个人,场地对。例如,如果用户1在早上9点将场地A评级为4,然后在下午5点再次评分为3,我只想使用3的等级,因为它是最近的。还有一些可选条件,例如更新的最近时间,以及用户必须在哪个用户ID数组内。

有没有人建议写这样的东西的最佳方法是干净有效?我写了下面的named_scope应该可以做到这一点,但它非常难看:

named_scope :with_avg_ratings,  lambda { |*params|
hash = params.first || {}
has_params = hash[:user_ids] || hash[:time_ago]
dir = hash[:dir] || 'DESC'
{
  :joins => %Q{
    LEFT JOIN (select user_id, venue_id, max(updated_at) as last_updated_at from updates 
    WHERE type = 'Review' GROUP BY user_id, venue_id) lu ON lu.venue_id = venues.id
    LEFT JOIN updates ON lu.last_updated_at = updates.updated_at 
    AND updates.venue_id = venues.id AND updates.user_id = lu.user_id
  },
  :select => "venues.*, ifnull(avg(rating),0) as avg_rating", 
  :group => "venues.id",
  :order => "avg_rating #{dir}",
  :conditions => Condition.block { |c|
    c.or { |a|
      a.and "updates.user_id", hash[:user_ids] if hash[:user_ids]
      a.and "updates.updated_at", '>', hash[:time_ago] if hash[:time_ago]
    } if has_params
    c.or "updates.id", 'is', nil if has_params
  }

}

}

我包含最后一个“updates.id is null”条件,因为即使他们没有与之关联的任何更新,我仍然希望返回场地。

谢谢, 埃里克

1 个答案:

答案 0 :(得分:1)

Yikes,这看起来像find_by_sql给我的工作。当你做一些复杂的事情时,我发现最好把这份工作从ActiveRecord和DIY中拿走。