我有几个系统包含用户表以及某种形式的业力/重量/声誉。有时它是用户发布的帖子数量,有时是用户在网站上的所有活动中收到的上/下票数。
USER {
id int
name string
karma int
}
如何使用这些数字来计算用户的“体重”或“权限”?例如,一位长期成员的投票通常比新用户的4票多得多。
我正在考虑将所有成员的总得分/业力/声誉加起来,然后试图提出1-100的比例。
SUM(user.points) / COUNT(user.*) = average user points
然后像
CEIL(userA.points / average user points) = their weight on an issue
然而,这方面也需要有一个曲线,因为我不希望有5000个帖子/业力的人输出20个新用户的票数。
答案 0 :(得分:1)
可能有一些资源可以为您提供参数,但您可能应该确切地决定您想要的而不是使用某些预定义的模型。我建议你定义一些规则,用于哪些用户组应该相等或哪些用户应该相等(例如10 0 karma用户= 1 5k karma用户)(等效性更容易使用),这将非常快速地为某些用户生成参数选择方程式。
使用log(已经建议),一些(分数)功率(如平方根)或甚至只是线性可以工作。
我建议使用newKarma = a.karma^b + c
之类的内容,而不应该难以解决a
,b
和c
。我建议您选择b
而不是尝试计算它。使用新用户(karma = 0)应该可以很容易地解决这个问题。猜测值接近你想要的可能比数学上确定它们更容易(因为一些规则不适合任何简单的等式)。
请注意,上面的c
是业力的偏移,这将为许多新用户提供比高业力用户更多的总业力。您可能还想考虑a.(karma + c)^b
或a.(karma + c)^b + d
。分析您定义的规则应该告诉您使用哪个规则。
更新:为c
编辑:您有一些SQL选项。临时表(带有总和)实际上可能是最快的。您也可以使用视图。虽然我不确定,但也可能在同一个表上进行连接。使用视图看起来像:(对于某些选择的a,b,c和d)(您可能还想为视图添加索引)
Votes(issueID, userID) // table structure
User(userID, karma, ...) // table structure
CREATE VIEW Sums AS
SELECT issueID, SUM(1*POWER(karma + 2, 3) + 4) AS sumVal
FROM Votes JOIN User ON User.userID = Votes.userID
GROUP BY issueID
查询:
SELECT (1*POWER(karma + 2, 3) + 4)/sumVal AS influenceOnIssue
FROM Votes JOIN User ON User.userID = Votes.userID
JOIN Sums on Sums.issueID = Votes.issueID
WHERE Votes.userID = @UserID AND Votes.issueID = @IssueID
简化可能是计算列= 1*POWER(karma + 2, 3) + 4
更快的选择是在插入/更新时计算派生的业力,或者通过使用附加列并使用触发器,或者在调用插入/更新之前计算,并使用新值调用insert / update。
答案 1 :(得分:1)
在数学上,您最好的选择是按相关用户的百分位排名日志加权。但是,这在SQL中很痛苦。
更简单的是作弊并假设平均值与中位数相同(统计上非常糟糕的假设,但编程方式更简单):
SELECT 1 - log10(SELECT COUNT (*) FROM user
WHERE (SUM(user.points) / COUNT(user.*)) < user.points)
/ SELECT (COUNT (*) from user))
通过这种方式,你的前10%的业力将有一半的普通用户的影响,几乎是一个菜鸟的影响的两倍。 显然,更改日志基础可以扩展这一点,其中自然日志(mysql中的log())会使上限10%的效果与菜鸟相同,是平均值的两倍。 Log2()更加极端。 (注意:需要减法,因为日志将为负数。)
如果您想要更严重的效果,可以尝试平方日志。 (注意:平方使对数平方为正,因此这里的加法是合适的。)
如果你想要一个超精确规则,你可以进入标准偏差,但是sql变得麻烦而且速度慢。这一切都取决于你想要去兔洞的距离......