简体   繁体   中英

Rails select and sort by aggregate of has_many

I have a Course model which has_many reviews. My Review model has a rating field. What I would like is a query to find the top rated courses. I want to do this in the SQL in order to avoid returning all the course objects and then trying to rank and sort them.

I would try this SQL:

SELECT courses.* FROM 
 (SELECT courses.*, count(*) as rating_no 
  FROM courses 
  JOIN reviews ON reviews.course_id = courses.id 
  GROUP BY reviews.course_id ) as res 
ORDER BY rating_no DESC 

the idea: You first take all data for each course, along with number of ratings. Then you just sort them. My experinece in MySQL is that GROUP BY and ORDER BY do not like each other, and that is why I used subquery. You might want to try on one query first though, but I doubt it will work :) If you are not interstend in just number of ratings, but for example actual average rate, you can make query like

SELECT courses.* FROM 
 (SELECT courses.*, (SUM(reviews.rating)/count(*)) as avg_rating 
  FROM courses 
  JOIN reviews ON reviews.course_id = courses.id 
  GROUP BY reviews.course_id HAVING count(*) > 0) as res 
ORDER BY rating_no DESC 

having count(*) >0 is most likely not needed, but just in case I have added it, to point out that you should avoid dividing by 0.

You don't describe how you define "top rated". It could be that you want the courses with the highest individual ratings:

Course.joins(:reviews).group("courses.id").order("reviews.rating desc")

Or you might want the courses with the highest total ratings:

Course.joins(:reviews).group("courses.id").order("sum(reviews.rating) desc")

Then on each of these you can call first(10) to get the top ten by whichever criteria you want.

you may try this

select  * from courses where review=(select max(rating) from table)

or

select top 1.* from courses order by review desc

Try this

@courses = Course.find(:all, :joins => "INNER JOIN reviews ON reviews.courses_id = courses.id", :order => "reviews.rating DESC")

or RAW sql

`SELECT `courses`.* FROM `courses` INNER JOIN reviews ON reviews.courses_id = courses.id ORDER BY reviews.rating DESC`

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM