2009-04-06 6 views
14

Je voudrais faire une somme sur les lignes dans une base de données et de groupe par date.Django GROUPE BY format date strftime

Je suis en train d'exécuter cette requête SQL en utilisant des agrégats de Django et annotations:

select strftime('%m/%d/%Y', time_stamp) as the_date, sum(numbers_data) 
    from my_model 
    group by the_date; 

J'ai essayé les éléments suivants:

data = My_Model.objects.values("strftime('%m/%d/%Y', 
      time_stamp)").annotate(Sum("numbers_data")).order_by() 

mais il semble que vous ne pouvez utiliser les noms de colonnes dans les valeurs() fonction; il n'aime pas l'utilisation de strftime().

Comment dois-je procéder?

+0

Juste trouvé ceci: http://code.djangoproject.com/ticket/10302 –

Répondre

14

Cela fonctionne pour moi:

select_data = {"d": """strftime('%%m/%%d/%%Y', time_stamp)"""} 

data = My_Model.objects.extra(select=select_data).values('d').annotate(Sum("numbers_data")).order_by() 

A pris un peu pour comprendre que je devais échapper aux signes%.

+0

J'ai quelque chose comme: 'Out [15]: ) a échoué: django.db.utils.OperationalError: (1305, 'FONCTION xxxxxx.strftime ne existe ')> ' des idées pourquoi? – user2002692

+0

Je reçois la même erreur. Avez-vous découvert pourquoi il ne pouvait pas reconnaître strftime? – Sid

1

Toute raison de ne pas le faire cela dans la base de données, en exécutant la requête suivante sur la base de données:

select date, sum(numbers_data) 
from my_model 
group by date; 

Si votre réponse est, la date est un datetime avec des heures de zéro, minutes, secondes , ou millisecondes, ma réponse est d'utiliser une fonction de date pour tronquer le datetime, mais je ne peux pas vous dire exactement ce que c'est sans savoir quel RBDMS vous utilisez.

+0

En ce moment j'emploie juste sqlite3 pour la preuve de co ncept. La "date" est en effet un champ datetime. J'utilisais strftime() pour tronquer le champ datetime à une date. Y at-il quelque chose de mieux pour sqlite3? Que voulez-vous dire par "faites-le dans la base de données"? Merci! –

+0

Je veux dire, il suffit d'utiliser n'importe quelle installation existante dans Django pour faire un choix SQL direct. – tpdi

1

Je ne suis pas sûr strftime, ma solution ci-dessous utilise sql postgres ... trunc

select_data = {"date": "date_trunc('day', creationtime)"}  
ttl = ReportWebclick.objects.using('cms')\ 
        .extra(select=select_data)\ 
        .filter(**filters)\ 
        .values('date', 'tone_name', 'singer', 'parthner', 'price', 'period')\ 
        .annotate(loadcount=Sum('loadcount'), buycount=Sum('buycount'), cancelcount=Sum('cancelcount'))\ 
        .order_by('date', 'parthner') 

- égale à l'exécution de la requête SQL:

 
select date_trunc('month', creationtime) as date, tone_name, sum(loadcount), sum(buycount), sum(cancelcount) 
from webclickstat 
group by tone_name, date; 
2

Au v1.8 , vous pouvez utiliser Func() expressions.

Par exemple, si vous souhaitez cibler la date de AWS Redshift et fonctions temps:

from django.db.models import F, Func, Value 

def TimezoneConvertedDateF(field_name, tz_name): 
    tz_fn = Func(Value(tz_name), F(field_name), function='CONVERT_TIMEZONE') 
    dt_fn = Func(tz_fn, function='TRUNC') 
    return dt_fn 

Ensuite, vous pouvez l'utiliser comme ceci:

SomeDbModel.objects \ 
.annotate(the_date=TimezoneConvertedDateF('some_timestamp_col_name', 
              'America/New_York')) \ 
.filter(the_date=...) 

ou comme ceci:

SomeDbModel.objects \ 
.annotate(the_date=TimezoneConvertedDateF('some_timestamp_col_name', 
              'America/New_York')) \ 
.values('the_date') \ 
.annotate(...)