4

product_date_added作为字段的每个产品 a都Date包含它的添加日期。它们还有一个product_viewswhich 是一个int包含产品被查看次数的字段。

为了按受欢迎程度显示产品,我使用了一种算法来计算产品每天的点击量。

SELECT 
    AVG(product_views / DATEDIFF(NOW(), product_date_added)) as avg_hits
    , product_table.* 
FROM product_table
WHERE product_available = "yes" 
GROUP BY product_id
ORDER BY avg_hits DESC

这行得通,但老板注意到很多旧产品首先出现。所以他基本上希望新观点比旧观点更有分量。

他的建议是,任何超过一年的浏览量都不算数。我认为我必须保留每个视图的日期才能做到这一点,我认为这会降低性能。

像我老板要求的那样创建流行度算法的最佳方法是什么?

理想情况下,我希望能够想出一些不会改变表结构的东西。如果那不可能,我至少想提出一个可以使用现有数据的解决方案,这样我们就不会从 0 开始。如果那也不可能,那么任何可行的方法都可以。

4

2 回答 2

2

您不必(因此)保留每个视图的日期。相反,您可以在包含以下列的表中为每个项目保留最多 366 行:product_id、day_of_year、count。每天运行一项任务,将一年前的所有计数归零。如果您不介意非规范化数据,该任务还可以更新项目本身的“计数”字段以便快速检索,这样您的查询就不需要更改。product_views就变成了product_views_in_the_last_year。1 天的时间段是任意的——我怀疑你是否关心流行度是基于恰好 1 年的窗口,所以我预计它可能只是一个小时、一周或两周,这取决于你有多少桶重新愿意处理。

另一种方案可能是使用指数衰减。将计数字段转换为十进制类型。每天一次,将每个项目的计数减少一个固定百分比(小于 1%,大于 0.1%),这样越是最近的命中,它的“权重”就越大。如此古老的人气永远不会完全消失,但一年前的热门歌曲不会有太大贡献。顺便说一句,与此方案等效的是,保留代码原样,但确保您的网站作为一个整体随着时间的推移呈指数级增长;-)

至于避免从零开始 - 作为一次性操作,可能会立即减少每个项目的计数,其比例取决于项目的年龄。总体而言,您希望旧对象具有旧视图,因此被当前方案高估。这不是万无一失的,因为也许一些较旧的项目最近获得了很多点击。您可以通过查看最近的 Web 服务器日志来识别这些项目,或者在进行一次性减少之前花费一周或一个月的时间来计算点击次数。即使不这样做,如果他们的受欢迎程度有一个根本原因(不仅仅是因为他们目前在您的排名中排名很高,因此从查看您的“最受欢迎”图表的人那里获得了流量),那么希望他们会在给定的时间内恢复.

于 2010-09-20T16:48:12.010 回答
1

您可能想查看这篇博文。它是针对 App Engine 的,但该技术是通用的。基本方法是让流行度呈指数衰减,并在您记录投票/下载/任何内容时增加。

于 2010-09-21T07:18:19.157 回答