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
字段排序的最新跟踪点。该查询还应该返回根本没有任何TrackingPoint
的Item
。如果可能的话,我不想使用QuerySet
的extra
方法来做到这一点。
这就是我到目前为止所尝试的......但失败了:(
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对相关一对多对象的聚合查询的主要内容,如果未能解决你的问题,请参考以下文章