ActiveRecord way of sorting a group before ordering
I have this active record query:
@reviews = Review.limit(30).group('user_id').order('created_at desc')
开发者_如何学JAVA
I'm using the group method to ensure I only display one review per user. The problem is that this review is not necessarily the last created review by that user.
I understand grouping happens before ordering so is it possible somehow to sort a group before calling order?
ids = Review.group(:user_id).maximum(:created_at).keys
@reviews = Review.limit(30).where(:id => ids).order(:created_at)
I have found many answers to this question but each requires raw sql, when you have simple query you can use it, for your input it will be something like this:
Review.find_by_sql(
"SELECT * FROM (
SELECT * FROM reviews
ORDER BY reviews.created_at DESC ) as my_table
group by my_table.user_id
LIMIT 30"
)
but if query is more complicated and need more joins then you can use the almost good solution mentioned earlier, I am not sure if it is the best solution but it works for me:
ids = Review.order('created_at DESC').pluck(:id)
@reviews = Review.where(id: ids).group(:user_id).limit(30)
edit: Yes, the last solution isn't right because it executes two queries to DB. I have accidently came back to this problem today and I have used the to_sql
method (shipped with > Rails 3.0) along with first solution, for me its perfect - 1. still one query, 2. subquery can be as complicated as you wish and the code readability will remain same:
Review.find_by_sql(
"SELECT * FROM (
#{ Review.order(:created_at).to_sql }
) as my_table
group by my_table.user_id
LIMIT 30"
)
精彩评论