PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

Django:Grupo de consultas por mês


Primeiro, você precisa fazer uma Function que possa extrair o mês para você:
from django.db import models
from django.db.models import Func

class Month(Func):
    function = 'EXTRACT'
    template = '%(function)s(MONTH from %(expressions)s)'
    output_field = models.IntegerField()

Depois disso tudo que você precisa fazer é
  1. anote cada linha com o mês
  2. agrupe os resultados pelo mês anotado usando values()
  3. anote cada resultado com a soma agregada dos totais usando Sum()

Importante :se sua classe de modelo tiver uma ordenação padrão especificada nas opções meta, você terá que adicionar um order_by() vazio cláusula. Isso é por causa de https://docs.djangoproject.com/en/1.9/topics/db/aggregation/#interaction-with-default-ordering-or-order-by

Campos que são mencionados no order_by() parte de um conjunto de consultas (ou que são usados ​​na ordenação padrão em um modelo) são usados ​​ao selecionar os dados de saída, mesmo que não sejam especificados de outra forma no values() ligar. Esses campos extras são usados ​​para agrupar resultados “like” e podem fazer com que linhas de resultados idênticas pareçam separadas.

Se você não tiver certeza, basta adicionar o order_by() vazio cláusula de qualquer forma, sem quaisquer efeitos adversos.

ou seja
from django.db.models import Sum

summary = (Invoice.objects
              .annotate(m=Month('date'))
              .values('m')
              .annotate(total=Sum('total'))
              .order_by())

Veja a essência completa aqui:https://gist.github.com/alvingonzales/ff9333e39d221981e5fc4cd6cdafdd17

Se precisar de mais informações:

Detalhes sobre como criar suas próprias classes Func:https://docs.djangoproject.com/en/1.8/ref/models/expressions/#func-expressions

Detalhes sobre a cláusula values(), (preste atenção em como ela interage com annotate() em relação à ordem das cláusulas):https://docs.djangoproject.com/en/1.9/topics/db/aggregation/#values

a ordem na qual as cláusulas annotate() e values() são aplicadas a uma consulta é significativa. Se a cláusula values() preceder a annotate(), a anotação será calculada usando o agrupamento descrito pela cláusula values().