首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Django annotate()多次导致错误答案

Django annotate()多次导致错误答案
EN

Stack Overflow用户
提问于 2009-08-12 09:35:05
回答 3查看 7.2K关注 0票数 28

Django为querysets提供了强大的new annotate()函数。但是,对于单个查询集中的多个注释,我无法让它正常工作。

例如,

代码语言:javascript
复制
tour_list = Tour.objects.all().annotate( Count('tourcomment') ).annotate( Count('history') )

一个浏览可以包含多个tourcomment和历史记录条目。我正在尝试获取此浏览的评论和历史记录条目的数量。由此产生的

代码语言:javascript
复制
history__count and tourcomment__count

值将是不正确的。如果只有一次annotate()调用,则该值将是正确的。

似乎有来自两个LEFT OUTER JOIN的某种乘法效应。例如,如果一个旅行有3个历史和3个评论,那么9将是这两个历史的计数值。对于两个值,12个历史记录+1个注释= 12个。1历史+0评论=1历史,0评论(这一次恰好返回正确的值)。

由此产生的SQL调用为:

代码语言:javascript
复制
SELECT `testapp_tour`.`id`, `testapp_tour`.`operator_id`, `testapp_tour`.`name`, `testapp_tour`.`region_id`, `testapp_tour`.`description`, `testapp_tour`.`net_price`, `testapp_tour`.`sales_price`, `testapp_tour`.`enabled`, `testapp_tour`.`num_views`, `testapp_tour`.`create_date`, `testapp_tour`.`modify_date`, `testapp_tour`.`image1`, `testapp_tour`.`image2`, `testapp_tour`.`image3`, `testapp_tour`.`image4`, `testapp_tour`.`notes`, `testapp_tour`.`pickup_time`, `testapp_tour`.`dropoff_time`, COUNT(`testapp_tourcomment`.`id`) AS `tourcomment__count`, COUNT(`testapp_history`.`id`) AS `history__count` 
FROM `testapp_tour` LEFT OUTER JOIN `testapp_tourcomment` ON (`testapp_tour`.`id` = `testapp_tourcomment`.`tour_id`) LEFT OUTER JOIN `testapp_history` ON (`testapp_tour`.`id` = `testapp_history`.`tour_id`)
GROUP BY `testapp_tour`.`id`
ORDER BY `testapp_tour`.`name` ASC

我尝试组合两个查询集的结果,这两个查询集包含对annotate ()的单个调用,但它不能正常工作……你不能保证顺序是一样的。它看起来过于复杂和凌乱,所以我一直在寻找更好的东西...

代码语言:javascript
复制
tour_list = Tour.objects.all().filter(operator__user__exact = request.user ).filter(enabled__exact = True).annotate( Count('tourcomment') )
tour_list_historycount = Tour.objects.all().filter( enabled__exact = True ).annotate( Count('history') )
for i,o in enumerate(tour_list):
    o.history__count = tour_list_historycount[i].history__count

谢谢你的帮助。Stackoverflow在过去用了很多已经回答的问题救了我的命,但我还没有找到这个问题的答案。

EN

回答 3

Stack Overflow用户

发布于 2009-08-12 15:06:28

感谢您的评论。这并不是很有效,但它引导我走上了正确的方向。我终于能够通过将distinct添加到两个Count()调用中来解决这个问题:

代码语言:javascript
复制
Count('tourcomment', distinct=True)
票数 59
EN

Stack Overflow用户

发布于 2019-04-15 18:08:38

代码语言:javascript
复制
tour_list = Tour.objects.all().annotate(tour_count=Count('tourcomment',distinct=True) ).annotate(history_count=Count('history',distinct=True) )

你必须添加distinct=True才能得到正确的结果,否则它将返回错误的答案。

票数 1
EN

Stack Overflow用户

发布于 2009-08-12 09:44:05

我不能保证这将解决您的问题,但尝试将.order_by()附加到您的调用。这就是:

代码语言:javascript
复制
tour_list = Tour.objects.all().annotate(Count('tourcomment')).annotate(Count('history')).order_by()

原因是django需要选择ORDER BY子句中的所有字段,这会导致选择其他相同的结果。通过附加.order_by(),您将完全删除ORDER By子句,从而防止这种情况发生。有关此问题的详细信息,请参阅the aggregation documentation

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1265190

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档