Subquery#
合計値のアノテート#
サブクエリの合計値:
- 合計対象レコードを OuterRefで条件指定してして絞り込む
values() で ユニークフィールドで GROUP BY する- 対象フィールドの合計値を
anotate する - アノテートしたフィールドを
values() で ValueList にしてSubqueryで返す(1件のはず)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| def verify():
from django.db.models import OuterRef, Subquery, F
from django.db.models.functions import Coalesce
from base.models.utils import aggr_sum_decimal as D
from decimal import Decimal
ref_query = dict(
book__company_code=OuterRef("company_code"),
book__processing_month=OuterRef("processing_month"),
account_code=OuterRef("account_code"),
account_item_code=OuterRef("account_item_code"),
advances_code=OuterRef("outsource_code"),
advances_branch_code=OuterRef("outsource_branch_code"),
)
def bookitem_sum(bookitem):
qs = (
bookitem.objects.filter(**ref_query)
.values(*ref_query.keys())
.annotate(total=D("amount"))
.values("total")
)
return Subquery(qs)
qs = models.CostOutsource.objects.annotate(
sum_debit=Coalesce(bookitem_sum(BookDebit), Decimal("0")),
sum_credit=Coalesce(bookitem_sum(BookCredit), Decimal("0")),
).exclude(debit_amount=F("sum_debit"), credit_amount=F("sum_credit"))
|
Bing#
Djangoのクエリセットで、別のテーブルのフィールドの合計値をSubqueryを使ってannotateすることができます¹。以下は、例です。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
| from django.db.models import Subquery, Sum
from django.db.models.functions import Coalesce
subquery = Subquery(
AnotherModel.objects.filter(
id=OuterModel.objects.filter(id=OuterModelId).values('another_model_id')
).annotate(
total=Coalesce(Sum('field_name'), 0)
).values('total')
)
result = OuterModel.objects.annotate(
total=subquery
).values('total')
|
この例では、AnotherModelという別のモデルから、OuterModelというモデルに対して、Subqueryを使ってannotateしています。この例を参考にして、あなたのコードに合わせて書き換えてみてください。
¹: Django:クエリを使用して列の値の合計を計算します - QA Stack
ソース: Bing との会話 2023/5/17