在 Django 查询中按月计数

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

下午好,

我正在努力解决一个问题。 最终,我有一些记录想要查询并按月获取计数。

最终,我的目标是提供一个如下所示的数据集:

Month, opened, closed
Jan, 2, 3
Feb, 1, 5

等等...过去六个月。

我一直用这个作为基础: Django:按月分组查询

这可以单独获取每个:

six_months_ago = datetime.now() - timedelta(days = 180)
open_six_months = (Rec.objects
   .annotate(open=Month('open_date'))
   .values('open')
   .annotate(rec_opened=Count('status', filter=Q(status__is_open=True)))
   .order_by())
        
closed_six_months = (Rec.objects
   .annotate(closed=Month('close_date'))
   .values('closed')
   .annotate(rec_closed=Count('status', filter=Q(status__is_open=False) and Q(close_date__isnull=False) ))
   .order_by())

并非所有记录都有截止日期。

这在测试时返回正确的数据,但它在两个不同的查询中。

如果可能的话,我希望拥有一个数据集。

是否有一种简单的方法可以将其合并到一个查询中,该查询具有单行,其中包含按月打开日期的计数和关闭日期的计数?

谢谢您的帮助。

BCBB

django django-rest-framework django-views django-orm
1个回答
0
投票

一个选择可能是将两者连接在一起:

from django.db.models import IntegerField, Q, Value
from django.db.models.functions import ExtractMonth

six_months_ago = datetime.now() - timedelta(days=180)
all_items = (
    Rec.objects.values(
        open=ExtractMonth('open_date'),
        closed=Value(None, output_field=IntegerField()),
    )
    .annotate(item=Count('status', filter=Q(status__is_open=True)))
    .order_by()
    .union(
        Rec.objects.values(
            open=Value(None, output_field=IntegerField()),
            closed=ExtractMonth('close_date'),
        )
        .annotate(
            item=Count(
                'status',
                filter=Q(status__is_open=False, close_date__isnull=False),
            )
        )
        .order_by(),
        all=True,
    )
)

然后我们后处理为:

result = {}
for item in all_items:
    month = item['open'] or item['close']
    record = result.setdefault(month, [0, 0])
    record[item['open'] is None] += item['item']

这会将每个月的数字映射到两个项目的列表上,第一个是当月打开的项目数量,第二个是当月关闭的项目数量。

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