【问题标题】:Annotate queryset with percentage grouped by date使用按日期分组的百分比注释查询集
【发布时间】:2020-03-31 18:16:50
【问题描述】:

假设我有以下模型:

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

我需要使用按月分组的每个category 的百分比(基于created_at 字段)注释Order 查询集。我设法编写了一个查询来计算每个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),
]

提前致谢。

【问题讨论】:

  • 你弄明白了吗?您应该查看 Windows 功能。您可以使用分区参数进行计算。 (1) 窗口分区按月和计数,(2) 按月分区和类别和计数,以及 (3) 划分步骤 1 和 2。如果有帮助,请告诉我。

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


【解决方案1】:

使用 Django 的 Window functions,正如 cmets 中的 @ac2001 所建议的那样,我设法得到了我需要的东西。

使用示例模型并假设我希望每个 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')
)

欢迎任何关于进一步简化的建议。

【讨论】:

    猜你喜欢
    • 2020-09-06
    • 2019-04-03
    • 1970-01-01
    • 2013-12-08
    • 2016-12-30
    • 2013-08-18
    • 1970-01-01
    • 1970-01-01
    • 2021-11-01
    相关资源
    最近更新 更多