Подсчет по месяцам в запросе Django
Добрый день,
Я борюсь с запросом. В конечном счете, у меня есть несколько записей, которые я хочу запросить и получить подсчет по месяцам.
В конечном счете, моя цель - получить набор данных, который выглядит следующим образом:
Month, opened, closed
Jan, 2, 3
Feb, 1, 5
И так далее... за последние шесть месяцев.
Я использовал это в качестве основы: Django: Query Group By Month
Это работает для получения каждого по отдельности:
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
Можно просто соединить две части вместе следующим образом:
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']
В этом случае каждый номер месяца будет отображаться в списке из двух элементов, первый из которых - количество предметов, открытых в этом месяце, а второй - количество предметов, закрытых в этом месяце.