合計値のアノテート
サブクエリの合計値:
- 合計対象レコードを OuterRefで条件指定してして絞り込む
values()で ユニークフィールドでGROUP BYする- 対象フィールドの合計値を
anotateする - アノテートしたフィールドを
values()で ValueList にしてSubqueryで返す(1件のはず)
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することができます¹。以下は、例です。
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
- (1) Django:クエリを使用して列の値の合計を計算します - QA Stack. https://qastack.jp/programming/8616343/django-calculate-the-sum-of-the-column-values-through-query.
- (2) DjangoのSubqueryを駆使して難解な条件をクリアする - Qiita. https://qiita.com/moonwalkerpoday/items/14cd76de201af956b2d1.
- (3) Djangoで集計をする方法を分かりやすく解説【具体的なコード …
https://codor.co.jp/django/how-to-use-aggregation.