如何在Python/SQLAlchemy/Flask中计算累积移动平均值

8
我会给出一些背景信息,以便更好地理解。我正在一个表格(评分)中捕获产品的客户评分,并希望能够返回基于时间的评分的累积移动平均值。
以下是一个基本示例,每天都有一个评分:
02 FEB - Rating: 5 - Cum Avg: 5
03 FEB - Rating: 4 - Cum Avg: (5+4)/2 = 4.5
04 FEB - Rating: 1 - Cum Avg: (5+4+1)/3 = 3.3
05 FEB - Rating: 5 - Cum Avg: (5+4+1+5)/4 = 3.75
Etc...

我正在尝试想出一个不会变得难以扩展的方法。

我的当前思路是,创建一个函数,当Rating表中插入一行时,该函数会根据该产品之前的行计算出Cum Avg。

因此,字段应该类似于:

TABLE: Rating
| RatingId | DateTime | ProdId | RatingVal | RatingCnt | CumAvg |

但这似乎是一种相当不可靠的存储数据的方式。

有什么方法(或任何方法)可以实现这个目标?如果我要使用某种“触发器”,那么在SQLAlchemy中如何操作?

非常感谢您的任何建议!


1
这在SQL中肯定是可行的 - 请参见:http://stackoverflow.com/questions/4107479/subqueries-aggregates-and-aggravation/4107784#4107784 ... 不过我不确定如何让SQLAlchemy生成这样的查询(而且您的数据库可能不支持必要的语法)。 - Sean Vieira
@Sean Vieria:感谢提供链接 - 我知道在纯SQL中是可能的,但是随着评分数量的增加,性能会变得越来越差,因为每行都要进行计算。我可能会尝试实现我的原始想法,即在输入每行时将其存储,因为我知道这样可以扩展。我只是不确定是否有什么基本的东西我忽略了。感谢您的帮助! - mal-wan
1个回答

5
我不太了解SQLAlchemy,但我可能会采用这样的方法:
  • 将累计平均值和评分数量与各个评分分开存储。
  • 每次获得新评分时,更新累计平均值和评分数量:
    • new_count = old_count + 1
    • new_average = ((old_average * old_count) + new_rating) / new_count
  • 可选地,为每个新评分存储一行。

使用单个SQL语句可以更新平均值和评分数量。


谢谢,我昨天实现了大部分内容,这是我最终采用的方法,我只需要完成实现它,然后我会发布我使用的代码。它可以负责任地和可预测地扩展,这正是我想要的。 - mal-wan
如果用户可以编辑评分,这种方法可行吗? - user2990084
1
存储“总和”和“计数”要比存储“平均值”和“计数”容易得多。 - Timothy Shields

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接