每个产品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开始。如果那不可能,那么任何工作都不可行。
答案 0 :(得分:2)
你不会(因此)必须保留每个视图的日期。相反,您可以在包含列的表中为每个项目保留最多366行:product_id,day_of_year,count。每天运行一项任务,将一年前的所有计数归零。如果您不介意非规范化数据,那么该任务还可以更新项目本身中的“计数”字段以便快速检索,这样您的查询就不需要更改。 product_views
只是product_views_in_the_last_year
。 1天的时间段是任意的 - 我怀疑你是否关心流行度是基于一年的窗口,所以我希望它也可以是一小时,一周或两周,这取决于你有多少桶?愿意处理。
另一种方案可能是使用指数衰减。将计数字段转换为十进制类型。每天一次,将每个项目的数量减少一个固定的百分比(小于1%,大于0.1%),以便命中越近,它的“重量”越多。如此古老的人气永远不会完全消亡,但一年前的点击量不会有多大贡献。顺便说一下,这个方案的一个等价是保持代码不变,但确保您的网站整体上随着时间的推移变得越来越受欢迎; - )
至于避免从零开始 - 可能会立即减少每个项目的计数,作为一次性动作,取决于项目的年龄。总的来说,您希望旧对象具有较旧的视图,因此被当前方案评级过高。这不是万无一失的,因为可能一些较旧的物品最近获得了大量的点击。您可以通过查看最近的Web服务器日志来识别这些项目,或者在执行一次性减少之前花费一周或一个月计算命中数。即使没有这样做,如果有一个根本原因让他们受欢迎(不仅仅是因为他们目前在你的排名中排名很高,因此从看着你“最受欢迎”图表的人那里获得流量),那么希望他们能够恢复时间
答案 1 :(得分:1)
您可能想查看this blog post。它的目标是App Engine,但技术很普遍。基本方法是使流行度呈指数级衰减,并且在您记录投票/下载/其他任何时候都会增加。