How to merge queryset into a single result without any repetation?
Can you try constructing one queryset using Case
and When
instead of union like:
from django.db.models import Case, When
final_set = GroupBase.objects.filter(base_group__group_ledger__company=company).annotate(
total_debit_positive=Case(
When(is_debit__exact='Yes', base_group__group_ledger__closing_balance__gt=0, then=Coalesce(Sum('base_group__group_ledger__closing_balance'), Value(0))),
default=Value(0),
output_field=FloatField()
),
total_debit_negative=Case(
When(is_debit__exact='Yes', base_group__group_ledger__closing_balance__lt=0, then=Coalesce(Sum('base_group__group_ledger__closing_balance'), Value(0))),
default=Value(0),
output_field=FloatField()
),
total_credit_positive=Case(
When(is_debit__exact='No', base_group__group_ledger__closing_balance__gt=0, then=Coalesce(Sum('base_group__group_ledger__closing_balance'), Value(0))),
default=Value(0),
output_field=FloatField()
),
total_credit_negative=Case(
When(is_debit__exact='No', base_group__group_ledger__closing_balance__lt=0, then=Coalesce(Sum('base_group__group_ledger__closing_balance'), Value(0))),
default=Value(0),
output_field=FloatField()
)
You can use the filter
argument for Sum
with a different Q
object for each annotation instead. Also use the values
method of the queryset to group the output by the name
field, so there won't be separate entries of the same name in the output:
final_set = GroupBase.objects.filter(
base_group__group_ledger__company=company).values('name').annotate(
total_debit_positive=Sum('base_group__group_ledger__closing_balance', output_field=FloatField(),
filter=Q(is_debit__exact='Yes', base_group__group_ledger__closing_balance__gt=0)),
total_debit_negative=Sum('base_group__group_ledger__closing_balance', output_field=FloatField(),
filter=Q(is_debit__exact='Yes', base_group__group_ledger__closing_balance__lt=0)),
total_credit_positive=Sum('base_group__group_ledger__closing_balance', output_field=FloatField(),
filter=Q(is_debit__exact='No', base_group__group_ledger__closing_balance__gt=0)),
total_credit_negative=Sum('base_group__group_ledger__closing_balance', output_field=FloatField(),
filter=Q(is_debit__exact='No', base_group__group_ledger__closing_balance__lt=0))
)
for g in final_set:
print(
g['name'], g['total_debit_positive'], g['total_debiit_negative'],
g['total_credit_positive'], g['total_credit_negative'], sep=' - '
)