使用按日期分组的百分比注释查询集

时间:2019-12-06 18:26:19

标签: django python-3.x django-models django-orm django-annotate

假设我有以下模型:

class Order(models.Model):
    category = models.CharField(max_length=100, choices=CATEGORY_CHOICES, default=DEFAULT_CHOICE)
    created_at = models.DateTimeField(auto_now_add=True)

我需要对Order查询集进行注释,并按月将每个category的百分比分组(基于created_at字段)。我设法写了一个查询来对按月分组的每个Order进行计数:

orders_per_month = (Order.objects
    .annotate(month=TruncMonth('created_at'))
    .values('month')
    .annotate(count=Count('id'))
    .order_by('month')
    .values('month', 'count')
)

仅将最后一个.values()更改为.values('month', 'category', 'count'),就可以得到按categorymonth分组的计数。

是否可以使用Django的ORM来获取按月分组的每个category的百分比?例如,如果我有以下数据:

MONTH | CATEGORY
Jan   | 'A'
Jan   | 'B'
Feb   | 'A'

我想得到类似的东西:

[
    (Jan, 'A', 0.5),
    (Jan, 'B', 0.5),
    (Feb, 'A', 1),
]

谢谢。

1 个答案:

答案 0 :(得分:0)

按照@ ac2001在评论中的建议,使用Django的Window functions,我设法获得了所需的东西。

使用示例模型并假设我想要按月分组的每个category的百分比:

orders_per_month = (Order.objects
    .annotate(month=TruncMonth('created_at'))
    .values('month', 'category')
    .distinct()
    .annotate(month_total=Window(
        expression=Count('id'),
        partition_by=[F('month')],
    ))
    .annotate(month_category=Window(
        expression=Count('id'),
        partition_by=[F('month'), F('category')],
    ))
    .annotate(percentage=ExpressionWrapper(
        F('month_category') * 100.0 / F('month_total'),
        output_field=FloatField()
    ))
    .values('month', 'percentage', 'category')
)

欢迎提出任何进一步简化此方法的建议。