可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I have two models users
and posts
. An user can votes and views a post
#users id name #posts id count_votes count_views users_id created_at updated_at
I want the user who received the most votes and views on his posts from the last 24 hours. The biggest sum of views and votes win.
WHAT I TRIED I have this SQL query, it's good but I would like to have the user with the max of votes, this one give me all users and I don't know how to add count_views
select u.name as "Name", sum(p.count_votes) from posts p inner join users u on p.user_id = u.id where p.created_at >= DATE_SUB(NOW(), INTERVAL 1 day) group by user_id;
ActiveRecord version
Post.select("users.id, sum(posts.count_votes) as nb_votes") .joins(:user).where("posts.created_at >= ?", 1.day.ago.beginning_of_day) .group("posts.user_id") # Results on IRB => #<ActiveRecord::Relation [#<Post id: 1>, #<Post id: 3>]>
How can I combine a sum and a max on these two sums ? Is there a way to have an activerecord code or only raw SQL ?
回答1:
You current query does a grouping on user. So you would get one record for each user in the output. By limiting the output to just 1 record and ordering by votes+views total count, you can get the top user.
Raw SQL:
select u.id, sum(p.count_votes + p.count_views) total from posts p inner join users u on p.user_id = u.id where p.created_at >= DATE_SUB(NOW(), INTERVAL 1 day) group by u.id order by total DESC limit 1 ;
ActiveRecord version: Start from your User model, so you will get the user object in the output instead of Post object, like you have mentioned in the question.
User.select("users.id, sum(posts.count_votes + posts.count_views) as nb_votes") .joins(:post).where("posts.created_at >= ?", 1.day.ago.beginning_of_day) .group("posts.user_id").order("nb_votes DESC").limit(1)
回答2:
ActiveRecord makes sense once you work with an object, in that case you need to have a User object only, so here is your solution below:
sql = %Q(SELECT * FROM users WHERE id = (SELECT users_id FROM posts WHERE DATE(created_at) = CURDATE() ORDER BY count_votes DESC, count_views DESC LIMIT 1 ) LIMIT 1) ActiveRecord::Base.connection.execute(sql)