PostgreSQL: five stars rating, ordering objects

孤街醉人 提交于 2019-12-24 19:53:26

问题


In my database users can add a vote from 1 to 5 stars to every groups. Then I have to display a leaderboard by those votes. What I was doing until now is to order them by votes average without a weight. This is not so nice because a group having 5.0 with 20 votes is before of a group having 4.9 avg and 10000 votes.

This is my votes table:

CREATE TABLE IF NOT EXISTS votes(
user_id BIGINT,
group_id BIGINT,
vote SMALLINT,
vote_date timestamp,
PRIMARY KEY (user_id, group_id)

This is how I sort them now:

SELECT 
      group_id,
      COUNT(vote) AS amount,
      ROUND(AVG(vote), 1) AS average, 
      RANK() OVER(PARTITION BY s.lang ORDER BY ROUND(AVG(VOTE), 1)DESC, COUNT(VOTE)DESC)
FROM votes
LEFT OUTER JOIN supergroups AS s 
USING (group_id)
GROUP BY group_id, s.lang, s.banned_until, s.bot_inside
HAVING 
      (s.banned_until IS NULL OR s.banned_until < now()) 
      AND COUNT(vote) >= %s 
      AND s.bot_inside IS TRUE

How could I add a sort of weight to solve the problem I said before?

I read about bayesan approach here but I am not sure if it's the right thing because I read it's about to sort the top 'n' elements, while I have to do a leaderboard including anyone of them.


回答1:


you're going to have to fudge it somehow, perhaps this way.

order by (0.0+sum(vote))/(count(vote)+log(count(vote)))

Or sqrt might work better than log, it depends how much weight you want the population size to have.

order by (0.0+sum(vote))/(count(vote)+sqrt(count(vote)))

basically the fudge needs to be a function that increases at a slower rate than it input. you could even try a constant.



来源:https://stackoverflow.com/questions/49561792/postgresql-five-stars-rating-ordering-objects

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!