python 处理注解表达式中聚合字段的除零操作

9ceoxa92  于 2023-01-08  发布在  Python
关注(0)|答案(1)|浏览(227)

当前在以下查询中,win_rate将始终默认为0,除非Lost为0-在这种情况下,win_rate将变为100。如何正确地允许对聚合字段进行除法运算,同时避免被零 debugging 误?

top_markets = list(opps
                   .annotate(name=Subquery(Market.objects.filter(id=OuterRef('market'))[:1].values('marketname')))
                   .order_by('name')
                   .values('name')
                   .annotate(opps=Count('id', filter=Q(datecreated__range=(start_date, end_date))),
                             Won=Count(
                                 'id', filter=Q(winloss='Won') & Q(date_closed__range=(start_date, end_date))),
                             Lost=Count('id', filter=Q(winloss='Lost') & Q(
                                 date_closed__range=(start_date, end_date))),
                             Concluded=F('Won') + F('Lost'))
                  )
                   .annotate(
                       win_rate=Case(
                           When(Won=0, then=0),
                           default=((F('Won')) / \
                                    (F('Won')) + F('Lost'))) * 100
                       )

编辑-
添加我的模型。opps是对模型Opportunity的预过滤查询:

class Opportunity(models.Model):
    name = models.CharField()
    winloss = models.CharField()
    market = models.ForeignKey(Market, on_delete=SET_NULL)
    datecreated = models.DateTimeField(auto_now=True)
rsaldnfx

rsaldnfx1#

将其转换为FloatField

from django.db.models import Count, F, FloatField, Q
from django.db.models.functions import Cast

opps.values(name=F('market__marketname')).annotate(
    opps=Count('id', filter=Q(datecreated__range=(start_date, end_date))),
    Won=Count(
        'id', filter=Q(winloss='Won', date_closed__range=(start_date, end_date))
    ),
    Lost=Count(
        'id', filter=Q(winloss='Lost', date_closed__range=(start_date, end_date))
    ),
    Concluded=F('Won') + F('Lost'),
    win_rate=Case(
        When(
            Concluded__gt=0,
            then=Cast('Won', output_field=FloatField())
            * 100
            / Cast('Concluded', output_field=FloatField()),
        ),
        default=0,
        output_field=FloatField(),
    ),
).order_by('name')

话虽如此,我还是不明白为什么要在数据库端这样做:你已经有了won的数量和列表Opportunity,所以你可以在Python/Django级别上做这些。此外,请不要使用queryset来生成序列化的数据:使用串行化程序。

相关问题