How to aggregate the average of a calculation based on two columns?

梦想的初衷 提交于 2019-12-11 13:48:58

问题


I want to write a Django query to give me the average across all rows in my table. My model looks like

class StatByDow(models.Model):
    total_score = models.DecimalField(default=0, max_digits=12, decimal_places=2)
    num_articles = models.IntegerField(default=0)
    day_of_week = IntegerField(
        null=True,
        validators=[
            MaxValueValidator(6),
            MinValueValidator(0)
        ]
    )

and I attempt to calculate the average like this

everything_avg = StatByDow.objects.all().aggregate(Avg(Func(F('total_score') / F('num_articles'))))

but this results in the error

  File "/Users/davea/Documents/workspace/mainsite_project/venv/lib/python3.7/site-packages/django/db/models/query.py", line 362, in aggregate
    raise TypeError("Complex aggregates require an alias")
TypeError: Complex aggregates require an alias

What's the right way to calculate the average?


回答1:


You don't need Func for the division, but you need to reconcile the two different field types. Use an ExpressionWrapper around Avg:

from django.db.models import ExpressionWrapper

everything_avg = (StatByDow.objects
    .aggregate(avg=ExpressionWrapper(
        Avg(F('total_score') / F('num_articles')),
        DecimalField()
    ))
)

You could also use a Cast from integer to decimal (not with PostgreSQL, which objects to Django's syntax ::numeric(NONE, NONE)) or an ExpressionWrapper around the division, but just one ExpressionWrapper at the end is the quickest solution as it happens once at the end.




回答2:


you need to pass a name of an alias (obviously by the error text) for aggregate function. the query should be something like this:

everything_avg = StatByDow.objects.all().aggregate(avg_f=Avg(Func(F('total_score') / F('num_articles'))))


来源:https://stackoverflow.com/questions/55458958/how-to-aggregate-the-average-of-a-calculation-based-on-two-columns

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!