Django аннотация, возвращающая неожиданное значение суммы - PullRequest
0 голосов
/ 09 мая 2020

Это мои модели:

class Consume(models.Model):
    amount = models.FloatField(default=1)
    entry_for = models.ForeignKey(
        Person,
        on_delete=models.SET_NULL,
        related_name='consume_entry_for',
    )


class Purchase(models.Model):
    amount = models.DecimalField(
        max_digits=6,
        decimal_places=2,
        default=0.00
    )
    entry_for = models.ForeignKey(
        Person,
        on_delete=models.CASCADE,
        related_name='ledger_entry_for',
    )

, а это мой запрос:

person_wise_total = Person.objects.annotate(
            total_purchase=Coalesce(Sum('ledger_entry_for__amount'), Value(0)),
            total_consume=Coalesce(Sum('consume_entry_for__amount'), Value(0))
        )

Например, у меня есть запись в Purchase

amount: 2, entry_for: jhon,
amount: 3, entry_for: smith
amount: 5, entry_for: jhon,
amount: 1, entry_for: jhon,

и consume запись:

amount: 1, entry_for: jhon,
amount: 2, entry_for: smith,

Согласно приведенным выше данным, мой запрос Sum должен возвращать total_consume для jhon 1, но он возвращает 3 для jhon в total_consume и smith total_consume составляет 2, здесь ожидается результат smith, но результат jhon неожиданный.

Я думаю, проблема / неправильный расчет, возникающий из-за того, что jhon имеет запись 3 в таблице Purchase, поэтому умножается на общая запись о покупке человека и общая сумма потребления, я не уверен, почему.

Кто-нибудь, пожалуйста, помогите мне, как я могу получить правильный расчетный результат?

Я хочу, он должен вернуться,

jhon's total_purchase: 8, total_consume: 1,
smith's total_purchase: 3, total_consume: 2

может ли кто-нибудь мне помочь в случае?

1 Ответ

1 голос
/ 09 мая 2020

Django использует таблицы объединений вместо подзапросов, когда есть несколько агрегатов, как уже задокументировано здесь

Объединение нескольких агрегатов с помощью annotate () даст неверный результат. результаты , потому что соединения используются вместо подзапросов

Вы должны написать подзапрос для каждой агрегации

...