Django annotate和values():'group by'中的额外字段会导致意外结果

oma*_*mat 3 django annotations group-by django-orm

我必须遗漏一些明显的东西,因为这种简单的要求不符合预期.这是我的模型类:

class Encounter(models.Model):
    activity_type = models.CharField(max_length=2, 
                           choices=(('ip','ip'), ('op','op'), ('ae', 'ae')))
    cost = models.DecimalField(max_digits=8, decimal_places=2)
Run Code Online (Sandbox Code Playgroud)

我想找到每种活动类型的总费用.我的查询是:

>>> Encounter.objects.values('activity_type').annotate(Sum('cost'))
Run Code Online (Sandbox Code Playgroud)

产量:

>>> [{'cost__sum': Decimal("140.00"), 'activity_type': u'ip'}, 
     {'cost__sum': Decimal("100.00"), 'activity_type': u'op'}, 
     {'cost__sum': Decimal("0.00"), 'activity_type': u'ip'}]
Run Code Online (Sandbox Code Playgroud)

在结果集中有2个'ip'类型遇到.这是因为它不是仅activity_type活动类型和成本分组,而是没有给出预期结果.生成的SQL查询是:

SELECT "encounter_encounter"."activity_type", 
    SUM("encounter_encounter"."total_cost") AS "total_cost__sum" 
    FROM "encounter_encounter" 
    GROUP BY "encounter_encounter"."activity_type", 
             "encounter_encounter"."total_cost"        <<<< THIS MESSES THINGS
    ORDER BY "encounter_encounter"."total_cost" DESC
Run Code Online (Sandbox Code Playgroud)

如何使这个查询按预期工作(如果我没有弄错的话,如文档所暗示的那样)并使它只进行一个分组activity_type

oma*_*mat 11

正如@Skirmantas正确指出的那样,问题与此有关order_by.虽然在查询中没有明确说明,但是模型的Meta类中的默认排序被添加到查询中,然后将其添加到group by子句中,因为SQL需要这样.

解决方案是删除默认排序或添加空order_by()重置顺序:

>>> Encounter.objects.values('activity_type').annotate(Sum('cost')).order_by()
Run Code Online (Sandbox Code Playgroud)