python 按月和年分组,但也包括0计数

ldioqlga  于 2023-03-11  发布在  Python
关注(0)|答案(1)|浏览(124)

我已经创建了一个查询集,它可以计算一个月和一年中的所有示例。我希望它也包括计数为0的月份。即使我的数据库中没有这些月份的示例,我该怎么做呢?

payments_per_month = PaymentRequest.objects
                     .annotate(year=Extract('arrival_date', 'year')).values('year')
                     .annotate(month=Extract('arrival_date', 'month')).annotate(count=Count('*'))
                     .values('year', 'month', 'count').order_by('-year', '-month', 'count')

输出为:

<QuerySet [{'year': 2023, 'month': 3, 'count': 8}, {'year': 2023, 'month': 2, 'count': 5}, 
           {'year': 2023, 'month': 1, 'count': 18}, {'year': 2022, 'month': 11, 'count': 2}, 
           {'year': 2022, 'month': 10, 'count': 1}, {'year': 2022, 'month': 8, 'count': 1}]>

例如,December(12)缺失,但我希望它在我的查询集中显示为:{'year': 2022, 'month': 12, 'count': 0}

uubf1zoe

uubf1zoe1#

要在查询集中包含计数为零的月份,可以先生成要包含在查询集中的所有月份的列表,然后使用此月份列表对查询集执行annotate操作,最后使用条件表达式对每个月份的示例进行计数。
请尝试以下操作:

from django.db.models import Case, When, Value, IntegerField

# Create a list of all the months
all_months = [
    {'month': 1}, {'month': 2}, {'month': 3}, {'month': 4},
    {'month': 5}, {'month': 6}, {'month': 7}, {'month': 8},
    {'month': 9}, {'month': 10}, {'month': 11}, {'month': 12},
]

# Annotate the queryset with the list of all months.

payments_per_month = PaymentRequest.objects \
    .annotate(year=Extract('arrival_date', 'year')) \
    .annotate(month=Value(all_months, output_field=JSONField())) \
    .values('year', 'month') \
    .annotate(count=Count('*')) \
    .order_by('-year', '-month')

# Use conditional expressions to count the instances of each month
payments_per_month = payments_per_month.annotate(
    count=Case(
        *[When(month__month=m['month'], then='count') for m in all_months],
        default=Value(0),
        output_field=IntegerField(),
    ),
)

# Extract the final queryset values
payments_per_month = payments_per_month.values('year', 'month__month', 'count').order_by('-year', '-month__month', 'count')

payments_per_month的第一个示例存储初始查询集,该查询集对当前和前一年的每个月的示例进行计数,但不包括计数为零的月份。
payments_per_month的第二个示例存储包含一年中所有月份(包括计数为零的月份)的最终查询集。此查询集是通过使用所有月份的列表注解初始查询集,然后使用条件表达式对每个月份的示例进行计数而生成的。
虽然payments_per_month的两个示例具有相同的名称,但是它们在代码的不同点引用不同的查询集,第一个示例被第二个示例覆盖,因此只有最后一个查询集存储在代码末尾的payments_per_month中。

相关问题