【问题标题】:Django aggregation and filteringDjango 聚合和过滤
【发布时间】:2018-04-18 22:56:38
【问题描述】:

我正在使用具有日期、组和标识符的模型。 我想为每个组检索最小日期值的 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 添加到这些元组的方法。 我尝试了 where date = min(date),但是 where 子句中禁止聚合。

【问题讨论】:

    标签: django django-queryset aggregation


    【解决方案1】:

    您可以在 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') 以获取最旧的项目,以防同一组中的同一天存在更多项目。如果日期是唯一的,则不需要。

    【讨论】:

    • 非常感谢您的回答!我检查了文档,它似乎正是我所需要的。我目前正在使用 Django==1.8.18,有没有等价的?
    • 如果date字段是当前日期那么你可以使用.annotate(Min('date'), Min('id'))否则你必须添加一条SQL,例如通过extra() 方法。您可以在 Django 1.11 中通过str(qs.query) 将其导出,并将具有子查询的字段的 SQL 粘贴到“extra”。 SubQuery 的示例与您的问题类似。这意味着以前不存在简单的解决方案。
    • 再次感谢您的回答,它解决了我的问题!
    猜你喜欢
    • 2011-08-19
    • 2016-08-13
    • 2014-12-17
    • 2017-03-09
    • 1970-01-01
    • 2012-07-24
    • 2020-09-11
    • 2018-06-16
    • 2011-09-09
    相关资源
    最近更新 更多