问题
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