Django注释子查询的聚合
Posted
技术标签:
【中文标题】Django注释子查询的聚合【英文标题】:Django annotate subquery's aggregation 【发布时间】:2020-05-23 15:32:50 【问题描述】:所以我有三个模型
class Advert(BaseModel):
company = models.ForeignKey(Company, on_delete=CASCADE, related_name="adverts")
class Company(BaseModel):
name = models.CharField(max_length=50)
class OrderRating(BaseModel):
reported_company = models.ForeignKey(Company, on_delete=CASCADE, related_name='ratings')
rating = models.DecimalField(
max_digits=2,
decimal_places=1,
validators=[MinValueValidator(1.0), MaxValueValidator(5.0)],
help_text='Rating from 1.0 to 5.0.'
)
当我这样做时,我正在尝试获取与公司相关的所有订单评级的平均值并将其注释到 Advert
模型:
qs = Advert.objects.all().annotate(
avg_rating=Subquery(
OrderRating.objects.filter(
reported_company=OuterRef('company')).aggregate(Avg("rating"))["rating__avg"]
)
)
我回来说明
This queryset contains a reference to an outer query and may only be used in a subquery.'
当我在Subquery
中调用OuterRef
时,不确定问题出在哪里。
【问题讨论】:
【参考方案1】:根据我的经验,Subqueries
通常有点棘手并且没有很好的文档记录。当定义子查询的代码中出现错误时,它们往往会返回您收到的消息(确实不是很有帮助的消息)。
据我所知aggregate
在Subequeries
中不起作用,您必须改用annotations
。所以这应该有效:
qs = Advert.objects.all().annotate(
avg_rating=Subquery(
OrderRating.objects.filter(
reported_company=OuterRef('company')).values('reported_company').annotate(av=Avg('rating')).values('av')
)
)
【讨论】:
这很遗憾总是返回一个空的查询集 你是说qs
还是avg_rating
是空的?
实际上刚刚开始工作,谢谢!这个问题非常有趣,在OrderRating
meta 我也有ordering = ['created_at']
,它不仅将sql查询翻译成ORDER BY reported_company
,而且翻译成ORDER BY reported_company, created_at
,这搞砸了一切,删除了固定的排序,现在给出了正确的输出.
太好了,你解决了。虽然...这篇文章中的查询没有使用任何order_by
?
是的,我在模型的元数据中有一个默认排序,无论如何,如果您有兴趣阅读它,这就是问题所在:docs.djangoproject.com/en/3.0/topics/db/aggregation/…以上是关于Django注释子查询的聚合的主要内容,如果未能解决你的问题,请参考以下文章
如何提高其 SET 涉及昂贵的聚合子查询的 SQL UPDATE 语句的性能?