Django : 날짜 별 그룹화 (일, 월, 연도)
다음과 같은 간단한 모델이 있습니다.
class Order(models.Model):
created = model.DateTimeField(auto_now_add=True)
total = models.IntegerField() # monetary value
그리고 다음의 월별 분석을 출력하고 싶습니다.
- 한 달 동안 판매 된 횟수 (
COUNT
) - 결합 된 값 (
SUM
)
이것을 공격하는 가장 좋은 방법이 무엇인지 모르겠습니다. 상당히 무섭게 보이는 추가 선택 쿼리를 보았지만 내 단순한 마음은 임의의 시작 연도 / 월에서 시작하여 현재 달에 도달 할 때까지 숫자를 반복하는 것이 더 나을 수 있다고 말합니다. 해당 월에 대한 쿼리 필터링. 더 많은 데이터베이스 작업-개발자 스트레스 감소!
당신에게 가장 의미있는 것은 무엇입니까? 빠른 데이터 테이블을 다시 가져올 수있는 좋은 방법이 있습니까? 아니면 내 더러운 방법이 아마도 최선의 생각일까요?
Django 1.3을 사용하고 있습니다. GROUP_BY
최근에 더 좋은 방법을 추가했는지 확실하지 않습니다 .
Django 1.10 이상
장고 문서 목록 extra
등이 빨리되지 . (@seddonym, @ Lucas03을 지적 해 주셔서 감사합니다). 나는 티켓을 열었고 이것은 jarshwah가 제공 한 솔루션입니다.
from django.db.models.functions import TruncMonth
from django.db.models import Count
Sales.objects
.annotate(month=TruncMonth('timestamp')) # Truncate to month and add to select list
.values('month') # Group By month
.annotate(c=Count('id')) # Select the count of the grouping
.values('month', 'c') # (might be redundant, haven't tested) select month and count
이전 버전
from django.db import connection
from django.db.models import Sum, Count
truncate_date = connection.ops.date_trunc_sql('month', 'created')
qs = Order.objects.extra({'month':truncate_date})
report = qs.values('month').annotate(Sum('total'), Count('pk')).order_by('month')
편집
- 추가 된 수
- 장고> = 1.10에 대한 정보 추가
@tback 답변에 약간의 추가 사항 : Django 1.10.6 및 postgres에서는 작동하지 않았습니다. 마지막에 order_by ()를 추가하여 수정했습니다.
from django.db.models.functions import TruncMonth
Sales.objects
.annotate(month=TruncMonth('timestamp')) # Truncate to month and add to select list
.values('month') # Group By month
.annotate(c=Count('id')) # Select the count of the grouping
.order_by()
또 다른 접근 방식은 ExtractMonth
. 하나의 datetime year 값만 반환되어 TruncMonth를 사용하는 데 문제가 발생했습니다. 예를 들어, 2009 년의 달만 반환되었습니다. ExtractMonth는이 문제를 완벽하게 해결했으며 아래와 같이 사용할 수 있습니다.
from django.db.models.functions import ExtractMonth
Sales.objects
.annotate(month=ExtractMonth('timestamp'))
.values('month')
.annotate(count=Count('id'))
.values('month', 'count')
metrics = {
'sales_sum': Sum('total'),
}
queryset = Order.objects.values('created__month')
.annotate(**metrics)
.order_by('created__month')
다음 queryset
은 판매 합계를 결합한 한 달에 한 줄의 주문 목록입니다.sales_sum
@ 장고 2.1.7
Here's my dirty method. It is dirty.
import datetime, decimal
from django.db.models import Count, Sum
from account.models import Order
d = []
# arbitrary starting dates
year = 2011
month = 12
cyear = datetime.date.today().year
cmonth = datetime.date.today().month
while year <= cyear:
while (year < cyear and month <= 12) or (year == cyear and month <= cmonth):
sales = Order.objects.filter(created__year=year, created__month=month).aggregate(Count('total'), Sum('total'))
d.append({
'year': year,
'month': month,
'sales': sales['total__count'] or 0,
'value': decimal.Decimal(sales['total__sum'] or 0),
})
month += 1
month = 1
year += 1
There may well be a better way of looping years/months but that's not really what I care about :)
Here is how you can group data by arbitrary periods of time:
from django.db.models import F, Sum
from django.db.models.functions import Extract, Cast
period_length = 60*15 # 15 minutes
# Annotate each order with a "period"
qs = Order.objects.annotate(
timestamp=Cast(Extract('date', 'epoch'), models.IntegerField()),
period=(F('timestamp') / period_length) * period_length,
)
# Group orders by period & calculate sum of totals for each period
qs.values('period').annotate(total=Sum(field))
By month:
Order.objects.filter().extra({'month':"Extract(month from created)"}).values_list('month').annotate(Count('id'))
By Year:
Order.objects.filter().extra({'year':"Extract(year from created)"}).values_list('year').annotate(Count('id'))
By day:
Order.objects.filter().extra({'day':"Extract(day from created)"}).values_list('day').annotate(Count('id'))
Don't forget to import Count
from django.db.models import Count
For django < 1.10
참고URL : https://stackoverflow.com/questions/8746014/django-group-by-date-day-month-year
'your programing' 카테고리의 다른 글
일식이 Avd 관리자 창 및 Android 프로젝트를 표시하지 않음 (0) | 2020.10.15 |
---|---|
Rails, javascript가 link_to helper를 클릭 한 후로드되지 않음 (0) | 2020.10.15 |
파일 모드가 명시 적으로 DOS 인 경우에도 캐리지 리턴 (^ M)을 표시하는 gVim (0) | 2020.10.15 |
파이썬에서 가장 짧은 스도쿠 솔버-어떻게 작동합니까? (0) | 2020.10.15 |
JavaScript 해시 맵은 어떻게 구현됩니까? (0) | 2020.10.15 |