每个产品a product_date_added 这是一个 Date 字段包含添加日期。他们也有一个 product_views 这是一个 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开始。

有帮助吗?

解决方案

您不会(因此)必须保留每个视图的日期。相反,您可以在包含列的表中每项最多366行:product_id,day_of_year,count。从一年前开始,每天将一项任务运行到零。如果您不介意不规范的数据,该任务还可以更新项目本身中的“计数”字段以进行快速检索,以便您的查询不需要更改。 product_views 只是变成 product_views_in_the_last_year. 。 1天的时间段是任意的 - 我怀疑您是否关心流行度是基于精确1年的窗口,因此我希望这可能是一个小时,一个星期或两周,具体取决于您多少桶。愿意应对。

另一种方案可能是使用指数衰减。将计数字段变成十进制类型。每天一次,将每个项目的计数降低固定百分比(小于1%,超过0.1%),因此最近的命中率越多,它的“权重”越多。因此,古老的受欢迎程度永远不会完全死亡,但一年前的热门歌曲并没有太大贡献。顺便说一句,等同于该方案的一个是离开代码,但请确保您的网站整体随着时间的流逝而变得更加流行;-)

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

其他提示

您可能想结帐 这篇博客文章. 。它针对App Engine,但该技术是一般的。基本方法是具有成倍衰减的普及,并在您记录投票/下载/其他任何时都会增加。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top