我有一个看起来像这样的模型:
class Payment(TimeStampModel):
timestamp = models.DateTimeField(auto_now_add=True)
amount = models.FloatField()
creator = models.ForeignKey(to='Payer')
计算每天平均支出的正确方法是什么? 我可以按天汇总,但是付款者不花任何钱的日子就不算在内,这是不正确的
更新:
因此,假设我的数据库中只有两条记录,一条来自3月1日,一条来自1月1日。平均每天的花费应该是
(Sum of all spendings) / (March 1 - January 1)
除以60
但是,这当然只会给我每件商品的平均支出,而天数会给我2:
for p in Payment.objects.all():
print(p.timestamp, p.amount)
p = Payment.objects.all().dates('timestamp','day').aggregate(Sum('amount'), Avg('amount'))
print(p
输出:
2019-03-05 17:33:06.490560+00:00 456.0
2019-01-05 17:33:06.476395+00:00 123.0
{'amount__sum': 579.0, 'amount__avg': 289.5}
答案 0 :(得分:1)
您可以汇总最小和最大时间戳以及金额的总和:
from django.db.models import Min, Max, Sum
def average_spending_per_day():
aggregate = Payment.objects.aggregate(Min('timestamp'), Max('timestamp'), Sum('amount'))
min_datetime = aggregate.get('timestamp__min')
if min_datetime is not None:
min_date = min_datetime.date()
max_date = aggregate.get('timestamp__max').date()
total_amount = aggregate.get('amount__sum')
days = (max_date - min_date).days + 1
return total_amount / days
return 0
如果存在min_datetime
,则db表中有一些数据,并且还有最大日期和总数,否则我们将返回0或任何您想要的值。
答案 1 :(得分:1)
这取决于您的后端,但是您想将金额之和除以最大时间戳和最小时间戳之间的天数差。在Postgres中,您可以简单地减去两个日期以获取它们之间的天数。在MySQL中,有一个名为DateDiff的函数,它接受两个日期并返回它们之间的天数。
class Date(Func):
function = 'DATE'
class MySQLDateDiff(Func):
function = 'DATEDIFF'
def __init__(self, *expressions, **extra):
expressions = [Date(exp) for exp in expressions]
extra['output_field'] = extra.get('output_field', IntegerField())
super().__init__(*expressions, **extra)
class PgDateDiff(Func):
template = "%(expressions)s"
arg_joiner = ' - '
def __init__(self, *expressions, **extra):
expressions = [Date(exp) for exp in expressions]
extra['output_field'] = extra.get('output_field', IntegerField())
super().__init__(*expressions, **extra)
agg = {
avg_spend: ExpressionWrapper(
Sum('amount') / (PgDateDiff(Max('timestamp'), Min('timestamp')) + Value(1)),
output_field=DecimalField())
}
avg_spend = Payment.objects.aggregate(**agg)
这对我来说似乎是正确的,当然,我还没有测试过。当然,如果这是您的后端,请使用MySQLDateDiff。