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

问题描述 投票:0回答:1

我创建了一个查询集,它计算一个月和一年中的所有实例。 我希望它做的还包括计数为 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}

python django django-models django-views django-queryset
1个回答
0
投票

要在查询集中包含计数为零的月份,您可以首先生成要包含在查询集中的所有月份的列表。然后,你可以

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
中。

© www.soinside.com 2019 - 2024. All rights reserved.