2012-08-24 9 views
8

次の設定では、すべてのタスク期間の合計(tasks_duration)とそのすべてのタスクの合計で注釈が付けられたプロジェクトのリストを含むQuerySetが必要ですサブタスク継続時間(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) 

私はこのように私のクエリセットを作る:行動に関連する

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

私はそれがあるべきよりもはるかに高いtasks_durationを得るDjango annotate() multiple times causes wrong answersで説明します。複数の注釈(Sum())節は、結果のSQL内で複数の左内部結合を生成します。 tasks_durationのアノテーション(Sum())という用語が1つしかない場合、結果は正しいです。しかし、私は両方のtask_durationとsubtasks_durationを持っていると思います。

このクエリを実行する適切な方法は何でしょうか?私はそれをプロジェクトごとに行う実用的な解決策を持っていますが、それは予想外に遅いです。私は余分な()呼び出しでも同様のことをしていますが、純粋なDjangoで私が望むものがあれば本当に知りたいです。

+0

:だから、トリックを使用してORM以下のように書くことができますリンク先の他の質問に記載されていますか? – jpic

+0

それは、私が望むものではない異なる持続時間の値を合計するためだけに役立つでしょう。私が試した好奇心から、同じ誤った値が得られます。 (期間は異なります) –

+0

この問題を回避する方法はありますか?私は1つのクエリーセットに合計と数を注釈することを試みており、その合計は増え続けています... – StephenTG

答えて

1

このエラーも発生します。正確に同じコード。私は集計を個別に行うと機能しますが、同時に両方の合計を取得しようとすると、そのうちの一方が2倍、残りが3倍になります。

Djangoがこのように動作する理由はわかりません方法。私はここにバグレポートを提出しました: https://code.djangoproject.com/ticket/19011 あなたもそれに従うことに興味があります。

+0

これは実際にDjangoのバグではありませんが、これらの集約クエリをデータベースに作成するという複雑さの問題です。 SQLを自分で作成したとしても、この問題を解決する必要があります。 – benjaoming

+1

関連するバグレポートへのリンク:https://code.djangoproject.com/ticket/10060 – benjaoming

+0

このバグはまだ修正されていません。 – sobolevn

1

バグはhereと報告されていますが、まだDjango 1.11では解決されていません。この問題は、逆の関係で2つのテーブルを結合することに関連しています。 個別のパラメータは、Countでは有効ですが、Sumではうまく機能しません。あなたのように `` tasks_duration =和( 'task__duration'、明瞭= TRUE)、subtasks_duration =合計( 'task__subtask__duration'、明瞭= true)をしようとしました

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'), 
) 
関連する問題