假设以下表格:
class Table1(models.Model):
Column1 = models.IntegerField()
class Table2(models.Model):
Column2 = models.IntegerField()
class Table3(models.Model):
Table1 = models.ForeignKey(Table1, null=False, on_delete=models.CASCADE)
Table2 = models.ForeignKey(Table2, null=False, on_delete=models.CASCADE)
Column3 = models.IntegerField()
class Table4(models.Model):
Table1 = models.ForeignKey(Table1, null=False, on_delete=models.CASCADE)
Table3 = models.ForeignKey(Table3, null=False, on_delete=models.CASCADE)
Column4 = models.IntegerField()
此注释表达式返回正确的答案:
print(Table1.objects.annotate(Exp1=Sum(
Case(
When(table3__Table2__Column2__in=[2, 3],
then=F('table3__Column3')),
default=Value(0)
),
)).values('Exp1'))
那是:
<QuerySet [{'Exp1': 96}]>
我需要定义另一个注释表达式,如下所示:
print(Table1.objects.annotate(Exp2=Sum(
Case(
When(table4__Table3__Table2__Column2=3,
then=F('table4__Column4')),
default=Value(0)
),
)).values('Exp2'))
结果再次正确:
<QuerySet [{'Exp2': 0}]>
最后,我想将这两个结合在一个命令中:
print(Table1.objects.annotate(Exp1=Sum(
Case(
When(table3__Table2__Column2__in=[2, 3],
then=F('table3__Column3')),
default=Value(0)
),
), Exp2=Sum(
Case(
When(table4__Table3__Table2__Column2=3,
then=F('table4__Column4')),
default=Value(0)
),
)).values('Exp1', 'Exp2'))
但不幸的是结果不正确:
<QuerySet [{'Exp2': 0, 'Exp1': 480}]>
答案 0 :(得分:1)
使用annotate
多个聚合时需要注意:
将多个聚合与
annotate()
组合将产生错误 结果是因为使用了连接而不是子查询。 对于大多数聚合,没有办法避免这个问题......
与使用Count
的聚合不同,Sum
不会使用可帮助重复项目的distinct
参数。如果要获得正确的结果,我想你应该保留不同的查询。
答案 1 :(得分:0)
报告错误here但即使在Django 1.11中也没有解决。该问题与以反向关系连接两个表有关。 请注意,distinct参数适用于Count但不适用于Sum。所以我使用了一个技巧并编写了下面的ORM,效果非常好:
print(Table1.objects.annotate(
temp_Exp1=Sum(
Case(
When(table3__Table2__Column2__in=[2, 3],
then=F('table3__Column3')),
default=Value(0)
),),
temp_Exp2=Sum(
Case(
When(table4__Table3__Table2__Column2=3,
then=F('table4__Column4')),
default=Value(0)
),),
table3_count=Count('table3'),
table3_count_distinct=Count('table3', distinct=True),
table4_count=Count('table4'),
table4_count_distinct=Count('table4', distinct=True),
).annotate(
Exp1=F('temp_Exp1')*F('table3_count_distinct')/F('table3_count'),
Exp2=F('temp_Exp2')*F('table4_count_distinct')/F('table4_count'),
).values('Exp1', 'Exp2'))