PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Django :groupe de requête par mois

Tout d'abord, vous devez créer une fonction qui peut extraire le mois pour vous :

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

Après cela, tout ce que vous avez à faire est

  1. annotez chaque ligne avec le mois
  2. regrouper les résultats par mois annoté en utilisant values()
  3. annotez chaque résultat avec la somme agrégée des totaux en utilisant Sum()

Important :si votre classe de modèle a un ordre par défaut spécifié dans les options méta, alors vous devrez ajouter un order_by() vide clause. C'est à cause de https://docs.djangoproject.com/en/1.9/topics/db/aggregation/#interaction-with-default-ordering-or-order-by

Champs mentionnés dans le order_by() partie d'un ensemble de requêtes (ou qui sont utilisées dans l'ordre par défaut sur un modèle) sont utilisées lors de la sélection des données de sortie, même si elles ne sont pas autrement spécifiées dans le values() appel. Ces champs supplémentaires sont utilisés pour regrouper les résultats "similaires" et ils peuvent faire apparaître des lignes de résultats par ailleurs identiques comme étant séparées.

Si vous n'êtes pas sûr, vous pouvez simplement ajouter le vide order_by() clause de toute façon sans aucun effet indésirable.

c'est-à-dire

from django.db.models import Sum

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

Voir l'essentiel ici :https://gist.github.com/alvingonzales/ff9333e39d221981e5fc4cd6cdafdd17

Si vous avez besoin de plus d'informations :

Détails sur la création de vos propres classes Func :https://docs.djangoproject.com/en/1.8/ref/models/expressions/#func-expressions

Détails sur la clause values(), (faites attention à la façon dont elle interagit avec annotate() par rapport à l'ordre des clauses) :https://docs.djangoproject.com/en/1.9/topics/db/aggregation/#values

l'ordre dans lequel les clauses annotate() et values() sont appliquées à une requête est important. Si la clause values() précède annotate(), l'annotation sera calculée à l'aide du regroupement décrit par la clause values().