gpt4 book ai didi

django - 多个注释和项产生夸张的答案

转载 作者:行者123 更新时间:2023-12-03 23:52:32 25 4
gpt4 key购买 nike

在下面的设置中,我想要一个带有项目列表的QuerySet,每个项目都用其所有任务持续时间的总和(如tasks_duration)及其所有任务的子任务持续时间的总和(如subtasks_duration)进行注释。我的模型(简化)如下所示:

class Project(models.Model):
pass

class Task(models.Model):
project = models.ForeignKey(Project)
duration = models.IntegerField(blank=True, null=True)

class SubTask(models.Model):
task = models.ForeignKey(Task)
duration = models.IntegerField(blank=True, null=True)


我使我的QuerySet像这样:

Projects.objects.annotate(tasks_duration=Sum('task__duration'), subtasks_duration=Sum('task__subtask__duration'))


Django annotate() multiple times causes wrong answers中解释的行为有关,我得到了一个task_duration,它比应有的要高得多。多个annotate(Sum())子句在结果SQL中产生多个左内部联接。仅对task_duration使用一个annotate(Sum())项,结果是正确的。但是,我想同时拥有task_duration和subtasks_duration。

什么是执行此查询的合适方法?我有一个可行的解决方案,可以针对每个项目执行此操作,但是这预计会非常慢。我还可以通过extra()调用进行类似操作,但我真的很想知道我想要的纯Django是否可以实现。

最佳答案

该错误报告为here,但即使在Django 1.11中也尚未解决。问题与以反向关系连接两个表有关。
请注意,对于Count而言,与众不同的参数适用,但对Sum而言则不适用。因此,您可以使用一个技巧来编写如下的ORM:

 Projects.objects.annotate(
temp_tasks_duration=Sum('task__duration'),
temp_subtasks_duration=Sum('task__subtask__duration'),
tasks_count=Count('task'),
tasks_count_distinct=Count('task', distinct=True),
task_subtasks_count=Count('task__subtask'),
task_subtasks_count_distinct=Count('task__subtask', distinct=True),
).annotate(
tasks_duration=F('temp_tasks_duration')*F('tasks_count_distinct')/F('tasks_count'),
subtasks_duration=F('temp_subtasks_duration')*F('subtasks_count_distinct')/F('subtasks_count'),
)


更新:
我发现您需要使用Subquery。在以下解决方案中,首先过滤与externalref相关的任务(外部查询的OuterRef引用,以便为每个Project过滤任务),然后按“ project”对任务进行分组,以使Sum适用于所有每个项目的任务,如果该项目存在任何任务(您已按“项目”过滤,然后按同一字段分组;这就是为什么只能有一组任务的原因),则仅返回一个结果。否则返回None。如果项目没有任务,结果将为“无”,这意味着我们无法使用[0]选择计算得出的总和。

from django.db.models import Subquery, OuterRef
Projects.objects.annotate(
tasks_duration=Subquery(
Task.objects.filter(
project=OuterRef('pk')
).values(
'project'
).annotate(
the_sum=Sum('task__duration'),
).values('the_sum')[:1]
),
subtasks_duration=Sum('task__subtask__duration')
)


运行此代码将只向数据库发送一个查询,因此性能很好。

关于django - 多个注释和项产生夸张的答案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12108710/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com