Django对相关一对多对象的聚合查询

Posted

技术标签:

【中文标题】Django对相关一对多对象的聚合查询【英文标题】:Django aggregation query on related one-to-many objects 【发布时间】:2011-02-19 19:34:07 【问题描述】:

这是我的简化模型:

class Item(models.Model):
    pass

class TrackingPoint(models.Model):
    item = models.ForeignKey(Item)
    created = models.DateField()
    data = models.IntegerField()

    class Meta:
        unique_together = ('item', 'created')

在我的应用程序的许多部分中,我需要检索一组Item 并使用data 字段从created 字段排序的每个项目的最新TrackingPoint 字段中注释每个项目。例如,Item 类的实例 i1 有 3 个 TrackingPoint 的:

tp1 = TrackingPoint(item=i1, created=date(2010,5,15), data=23)
tp2 = TrackingPoint(item=i1, created=date(2010,5,14), data=21)
tp3 = TrackingPoint(item=i1, created=date(2010,5,12), data=120)

我需要一个查询来检索带有tp1.data 字段值注释的i1 实例,因为tp1 是由created 字段排序的最新跟踪点。该查询还应该返回根本没有任何TrackingPointItem。如果可能的话,我不想使用QuerySetextra 方法来做到这一点。

这就是我到目前为止所尝试的......但失败了:(

Item.objects.annotate(max_created=Max('trackingpoint__created'),
                      data=Avg('trackingpoint__data')).filter(trackingpoint__created=F('max_created'))

有什么想法吗?

【问题讨论】:

【参考方案1】:

这是一个提供(TrackingPoint,Item)对的查询:

TrackingPoint.objects.annotate(max=Max('item__trackingpoint__created')).filter(max=F('created')).select_related('item').order_by('created')

您必须单独查询没有 TrackingPoints 的项目。

【讨论】:

【参考方案2】:

这不是直接回答您的问题,但如果不需要您所描述的确切内容,您可能会对每个组的最大 n 个解决方案感兴趣。你可以看看我对类似问题的回答:

Django Query That Get Most Recent Objects From Different Categories

-- 这应该直接适用于您的情况:

 items = Item.objects.annotate(tracking_point_created=Max('trackingpoint__created')) 
 trackingpoints = TrackingPoint.objects.filter(created__in=[b.tracking_point_created for b in items])

请注意,如果 created 日期在 TrackingPoint 模型中重复,则第二行可能会产生模棱两可的结果。

【讨论】:

您的解决方案遍历所有items,我负担不起。 created 在一项中是唯一的,我已经更新了我的问题。

以上是关于Django对相关一对多对象的聚合查询的主要内容,如果未能解决你的问题,请参考以下文章

Django——model基础

第六模块:WEB框架开发 第1章·Django框架开发50~100

Django - 以一对多关系更改相关对象的值

Django CRM查询(一对多,多对多以及相关的反查)

django 一对多跨表查询多对多

Django之ORM跨表操作(聚合查询,分组查询,F和Q查询等)