Ich habe ein einfaches Modell wie dieses:
class Order(models.Model):
created = model.DateTimeField(auto_now_add=True)
total = models.IntegerField() # monetary value
Und ich möchte eine monatliche Aufschlüsselung von:
- Wie viele Verkäufe gab es in einem Monat (
COUNT
) - Der kombinierte Wert (
SUM
)
Ich bin mir nicht sicher, wie ich das am besten angreifen kann. Ich habe einige ziemlich beängstigend aussehende Extra-Select-Abfragen gesehen, aber mein einfacher Verstand sagt mir, dass ich vielleicht besser dran bin, nur Zahlen zu iterieren, beginnend mit einem willkürlichen Startjahr / Monat und bis zum Erreichen des aktuellen Monats zu zählen und einfach wegzuwerfen Abfragen, die für diesen Monat gefiltert werden. Mehr Datenbankarbeit - weniger Entwicklerstress!
Was macht für Sie am meisten Sinn? Gibt es eine gute Möglichkeit, eine schnelle Datentabelle zurückzuziehen? Oder ist meine schmutzige Methode wahrscheinlich die beste Idee?
Ich benutze Django 1.3. Ich bin mir nicht sicher, ob sie in GROUP_BY
letzter Zeit einen schöneren Weg hinzugefügt haben .
Antworten:
Django 1.10 und höher
Die Django-Dokumentation wird bald
extra
als veraltet eingestuft . (Danke, dass Sie auf @seddonym, @ Lucas03 hingewiesen haben). Ich habe ein Ticket geöffnet und dies ist die Lösung, die Jarshwah bereitgestellt hat.ältere Versionen
Bearbeitungen
quelle
>>> qs.extra({'month':td}).values('month').annotate(Sum('total')) [{'total__sum': Decimal('1234.56'), 'month': datetime.datetime(2011, 12, 1, 0, 0)}]
'{}.timestamp'.format(model._meta.db_table)
USE_TZ
Einstellung aktiviert istTrue
, sind die beiden Versionen nicht genau gleichwertig. Die verwendete VersionTruncMonth
konvertiert den ZeitstempelTIME_ZONE
vor dem Abschneiden in die durch die Einstellung angegebene Zeitzone , während die verwendete Versiondate_trunc_sql
den unformatierten UTC-Zeitstempel in der Datenbank abschneidet.Nur eine kleine Ergänzung zu @tback Antwort: Es hat bei mir mit Django 1.10.6 und Postgres nicht funktioniert. Ich habe am Ende order_by () hinzugefügt, um das Problem zu beheben.
quelle
TruncDate
Ermöglicht die Gruppierung nach Datum (Tag des Monats)Ein anderer Ansatz ist zu verwenden
ExtractMonth
. Bei der Verwendung von TruncMonth sind Probleme aufgetreten, da nur ein Datum / Uhrzeit-Jahreswert zurückgegeben wurde. Beispielsweise wurden nur die Monate 2009 zurückgegeben. ExtractMonth hat dieses Problem perfekt behoben und kann wie folgt verwendet werden:quelle
Dies
queryset
ist eine Liste der Bestellungen, eine Zeile pro Monat, die die Summe der Verkäufe kombiniert:sales_sum
@ Django 2.1.7
quelle
Hier ist meine schmutzige Methode. Es ist schmutzig.
Es gibt vielleicht eine bessere Möglichkeit, Jahre / Monate zu wiederholen, aber das interessiert mich nicht wirklich :)
quelle
So können Sie Daten nach beliebigen Zeiträumen gruppieren:
quelle
Nach Monaten:
Pro Jahr:
Tagsüber:
Vergessen Sie nicht, Count zu importieren
Für Django <1.10
quelle