Как написать SQL-выражение Case() с агрегированным полем (Sum) с помощью конструктора запросов Django

Я пытаюсь воссоздать этот SQL-оператор с помощью конструктора запросов Django:

CASE
  WHEN sum(imps) = 0 THEN NULL
  ELSE SUM(total_expenses) / (sum(imps) / 1000)
END as "cpm"

Я пробовал:

MyModel.objects.annotate(
  cpm=Case(
    When(
      Sum("imps")>0,
      then=Sum("total_expenses") / Sum("imps"),
    ),
    default=0,
    output_field=FloatField(),
 )
)

Однако это не работает из-за этой ошибки типа '>' not supported between instances of 'Sum' and 'int'.

Если бы существовал поиск по полю, позволяющий сделать total_imps__sum__gt=0, я уверен, что это решило бы проблему.

Примечание:

Добавление Sum("imps") в качестве аннотации (total_imps=Sum("imps")) и выполнение total_imps__gt=0 работает, но это не идеальное решение, поскольку мне придется создавать несколько аннотаций для полей, которые мне не понадобятся.

Используйте NullIf вместо

MyModel.objects.annotate( 
    Cast(
        Sum("total_expenses") /1.0/ NullIf(Sum("imps"), 0)
        output_field=FloatField()
    ),
)

Вы можете использовать alias() в исходном запросе, чтобы не добавлять дополнительную аннотацию

Вернуться на верх