首页 > 解决方案 > 如何聚合基于两列的计算平均值?

问题描述

我想写一个 Django 查询来给我表中所有行的平均值。我的模型看起来像

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

我尝试像这样计算平均值

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

但这会导致错误

  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

计算平均值的正确方法是什么?

标签: pythondjangoaveragedjango-orm

解决方案


您不需要Func除法,但您需要协调两种不同的字段类型。使用ExpressionWrapper周围Avg

from django.db.models import ExpressionWrapper

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

您还可以使用Cast从整数到十进制的 a(不适用于 PostgreSQL,它反对 Django 的语法::numeric(NONE, NONE))或ExpressionWrapper围绕除法,但ExpressionWrapper最后只有一个是最快的解决方案,因为它在最后发生一次。


推荐阅读