PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

Django:gruppo di query per mese

Innanzitutto, devi creare una funzione che possa estrarre il mese per te:

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()

Dopodiché tutto ciò che devi fare è

  1. annota ogni riga con il mese
  2. raggruppa i risultati per mese annotato utilizzando values()
  3. annota ogni risultato con la somma aggregata dei totali usando Sum()

Importante :se la tua classe modello ha un ordinamento predefinito specificato nelle meta opzioni, dovrai aggiungere un order_by() vuoto clausola. Ciò è dovuto a https://docs.djangoproject.com/en/1.9/topics/db/aggregation/#interaction-with-default-ordering-or-order-by

Campi citati in order_by() parte di un set di query (o che vengono utilizzati nell'ordinamento predefinito su un modello) vengono utilizzati quando si selezionano i dati di output, anche se non sono altrimenti specificati in values() chiamata. Questi campi aggiuntivi vengono utilizzati per raggruppare i risultati "mi piace" e possono far sembrare separate righe di risultati altrimenti identiche.

Se non sei sicuro, puoi semplicemente aggiungere il vuoto order_by() clausola comunque senza effetti negativi.

cioè

from django.db.models import Sum

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

Vedi il succo completo qui:https://gist.github.com/alvingonzales/ff9333e39d221981e5fc4cd6cdafdd17

Se hai bisogno di ulteriori informazioni:

Dettagli sulla creazione delle tue classi Func:https://docs.djangoproject.com/en/1.8/ref/models/expressions/#func-expressions

Dettagli sulla clausola values(), (attenzione a come interagisce con annotate() rispetto all'ordine delle clausole):https://docs.djangoproject.com/en/1.9/topics/db/aggregation/#values

l'ordine in cui le clausole annotate() e values() vengono applicate a una query è significativo. Se la clausola values() precede annotate(), l'annotazione verrà calcolata utilizzando il raggruppamento descritto dalla clausola values().