Django聚合和过滤

时间:2017-11-06 17:40:07

标签: django django-queryset aggregation

我正在使用具有日期,组和标识符的模型。 我想为每个组检索最小日期值的id。

我的模特:

class MyModel(models.Model):
    group = models.ForeignKey('myapp.Group')
    date = models.DateTimeField(blank=True, null=True)

目标是检索这个:

[
    (u'group1', datetime.date(2016, 1, 23), 15 <- Id of the minimum date for group1),
    (u'group2', datetime.date(2015, 6, 25), 314 <- Id of the minimum date for group2),
    ...
]

我尝试了以下内容:

MyModel.objects.values_list('group').annotate(Min('date')).order_by('group')

这样可以正常工作,但只给我一个日期:

[
    (u'group1', datetime.date(2016, 1, 23)), 
    (u'group2', datetime.date(2015, 6, 25)), 
    (u'group3', datetime.date(2015, 6, 26))
    ...
]

我找不到在不破坏SQL中的分组子句的情况下将id添加到这些元组的方法。 我试着做一个date = min(date)的地方,但在where子句中禁止聚合。

1 个答案:

答案 0 :(得分:0)

您可以在Django 1.11中使用Subquery()表达式。

from django.db.models import OuterRef, Subquery

oldest = MyModel.objects.filter(group=OuterRef('group')).order_by('date', 'id')
qs = (
    MyModel.objects
    .values_list('group')
    .annotate(
        Min('date'),
        Subquery(oldest.values('id')[:1]),
    )
    .order_by('group')
)

如果同一组中同一天存在更多项目,则'id'字段会添加到.order_by('date', 'id')以获取最旧的项目。如果日期是唯一的,则没有必要。