【问题标题】:Django Query: Return average monthly spend per userDjango Query:返回每个用户的平均每月支出
【发布时间】:2022-11-09 09:00:09
【问题描述】:

给定一个存储用户交易的 Django 模型,我如何创建一个查询来返回每个用户的平均每月支出?

我当前的解决方案查询所有事务,迭代结果并使用字典计算每个用户的平均值。我知道有一种更有效的方法可以使用aggregate/annotate 进行查询,但不确定如何编写。

我更关心可读性而不是速度,因为数据库中的事务数量相对较少并且永远不会改变。

模型.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()

【问题讨论】:

  • 您使用的是哪个数据库?你想要有年份的月份,还是只是不考虑年份的月份的平均值?是 2022 年 3 月的平均值,还是所有年份 3 月交易的平均值?
  • 我正在使用 mysql,我需要年份月份的平均值,例如(2022 年 3 月)

标签: python django django-models django-orm


【解决方案1】:

对此深夜刺痛(未经测试)。下面的代码从日期中提取出年份和月份,然后用 order_by() 清除订单(可能并非所有情况都需要),然后按 'user'、'year'、'month' 分组并计算平均值,使用 Avg 函数存储在名为“平均”的列中。

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')
        

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-11
  • 1970-01-01
  • 1970-01-01
  • 2017-08-04
相关资源
最近更新 更多