Django:计算每个用户的平均每月支出
Django: Calculate average monthly spend per user
给定一个存储用户交易的 Django 模型,我如何创建一个查询 returns 每个用户的平均每月支出?
我当前的解决方案查询所有交易,迭代结果并使用字典计算每个用户的平均值。我知道有一种更有效的方法可以使用 aggregate/annotate
来查询它,但不确定如何编写它。
我更关心可读性而不是速度,因为数据库中的事务数量相对较少并且永远不会改变。
models.py
Class Transactions(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey('User', on_delete=models.CASCADE)
amount = models.DecimalField(max_digits=100, decimal_places=2)
date = models.DateField()
深夜研究这个(未经测试)。下面的代码从日期中提取年和月,然后使用 order_by() 清除顺序(可能并非在所有情况下都需要),然后按 'user'、'year' 分组, 'month' 并计算平均值,使用 Avg 函数存储在名为 'average' 的列中。
Documentation 还有其他一些很好的例子。
from django.db.models.functions import ExtractMonth, ExtractYear
from django.db.models import Avg
...
avg_by_user_by_month = Transactions.objects
.annotate(month=ExtractMonth('date'),
year=ExtractYear('date'),) \
.order_by()\
.values('user', 'year', 'month')\
.annotate(average=Avg('amount'))\
.values('user', 'year', 'month', 'average')
编辑
或者,这也可能有效:
from django.db.models import Avg, F
...
avg_by_user_by_month = Transactions.objects
.annotate(month=F('date__month'),
year=F('date__year'),) \
.order_by()\
.values('user', 'year', 'month')\
.annotate(average=Avg('amount'))\
.values('user', 'year', 'month', 'average')
给定一个存储用户交易的 Django 模型,我如何创建一个查询 returns 每个用户的平均每月支出?
我当前的解决方案查询所有交易,迭代结果并使用字典计算每个用户的平均值。我知道有一种更有效的方法可以使用 aggregate/annotate
来查询它,但不确定如何编写它。
我更关心可读性而不是速度,因为数据库中的事务数量相对较少并且永远不会改变。
models.py
Class Transactions(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey('User', on_delete=models.CASCADE)
amount = models.DecimalField(max_digits=100, decimal_places=2)
date = models.DateField()
深夜研究这个(未经测试)。下面的代码从日期中提取年和月,然后使用 order_by() 清除顺序(可能并非在所有情况下都需要),然后按 'user'、'year' 分组, 'month' 并计算平均值,使用 Avg 函数存储在名为 'average' 的列中。
Documentation 还有其他一些很好的例子。
from django.db.models.functions import ExtractMonth, ExtractYear
from django.db.models import Avg
...
avg_by_user_by_month = Transactions.objects
.annotate(month=ExtractMonth('date'),
year=ExtractYear('date'),) \
.order_by()\
.values('user', 'year', 'month')\
.annotate(average=Avg('amount'))\
.values('user', 'year', 'month', 'average')
编辑 或者,这也可能有效:
from django.db.models import Avg, F
...
avg_by_user_by_month = Transactions.objects
.annotate(month=F('date__month'),
year=F('date__year'),) \
.order_by()\
.values('user', 'year', 'month')\
.annotate(average=Avg('amount'))\
.values('user', 'year', 'month', 'average')