具有反向关系的多个Sum聚合的不同值

时间:2017-07-04 13:01:06

标签: django django-orm

根据Django docs组合使用annotate()的多个聚合将产生错误的结果,因为使用连接而不是子查询。他们还注意到,Count有一个可能有用的独特参数。

是否有与Sum类似的内容?在这个剥离的例子中,我最终得到了错误的结果。结果amount值对于大多数项目来说太高了。

qs = Client.filter('project__date__year=2017').annotate(
    isum=Sum('project__intoffer__amount', distinct=True),
    esum=Sum('project__extoffer__amount', distinct=True)
)

distinct=True参数没有任何区别。

简化models.py

class Client(models.Model):
    title = models.CharField('Title', max_length=50)

class Project(models.Model):
    title = models.CharField('Title', max_length=100)
    client = models.ForeignKey('Client', verbose_name='Client')
    date = models.DateField('Date', blank=True, null=True)

class IntOffer(models.Model):
    project = models.ForeignKey(Project, verbose_name='Project')
    amount = models.DecimalField('Amount', max_digits=19, decimal_places=2)

class ExtOffer(models.Model):
    project = models.ForeignKey(Project, verbose_name='Project')
    amount = models.DecimalField('Amount', max_digits=19, decimal_places=2)

1 个答案:

答案 0 :(得分:3)

您可以尝试使用django Subquery expression。在您的情况下,您的查询如下所示:

from django.db.models import Sum, OuterRef, Subquery

qs = Client.filter('project__date__year=2017').annotate(
    isum=Subquery(Project.objects.filter(client=OuterRef('pk')).values('client_id').annotate(sum=Sum('intoffer__amount')).values('sum')[:1]),
    esum=Subquery(Project.objects.filter(client=OuterRef('pk')).values('client_id').annotate(sum=Sum('extoffer__amount')).values('sum')[:1])
)

请注意,在大型表上它可能会很慢,在这种情况下使用RawSQL可能会更好。