У меня есть 3 таблицы - места, пользователи и обновления (у которых есть целое число для оценки) - и я хочу написать запрос, который вернет список всех моих мест, а также их средние оценки используя только последнее обновление для каждого человека, место встречи. Например, если пользователь 1 оценивает место проведения A один раз в 9 утра с 4, а затем оценивает его снова в 17:00 с 3, я хочу использовать рейтинг 3, поскольку он более поздний. Существуют также некоторые необязательные условия, например, как последние обновления должны быть, и если есть массив идентификаторов пользователей, пользователи должны находиться внутри.Сложные запросы в Rails
Есть ли у кого-нибудь предложение о том, что лучший способ написать что-то вроде этого так, чтобы он был чистым и эффективным? Я написал следующее 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 является нулевым» состоянием, потому что я все еще хочу, чтобы места вернулись даже если у них нет связанных с ними обновлений.
Спасибо, Эрик