我需要計算一個表的平均日期時間,我正在使用聚合與平均但它返回一個浮點型數字而不是日期時間對象。這個浮點數表示什麼?Django的數據庫平均的DateTimeField
而且,最重要的是,如何將它轉換爲日期時間對象?
我需要計算一個表的平均日期時間,我正在使用聚合與平均但它返回一個浮點型數字而不是日期時間對象。這個浮點數表示什麼?Django的數據庫平均的DateTimeField
而且,最重要的是,如何將它轉換爲日期時間對象?
剛剛跑我自己的模型測試,這似乎是今年
更多參考平均,我不得不面對類似的問題。考慮到車型:
class Championship(models.Model):
...
class Game(models.Model):
date = models.DateField()
championship = models.ForeignKey(Championship)
有些遊戲都涉及到一個總冠軍,我想,從這個冠軍重返遊戲的日期的平均值,例如,如果我有1月1日,一個一個遊戲在1月3日的比賽中,我想回到1月2日。
在PostgreSQL的背景下,天真的使用內置的魅力,使聚集沒有工作:(因爲平均並沒有被設計爲日期時間字段)
>>> championship.game_set.aggregate(Avg('date'))
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "~/env/local/lib/python2.7/site-packages/django/db/models/manager.py", line 158, in aggregate
return self.get_query_set().aggregate(*args, **kwargs)
File "~/env/local/lib/python2.7/site-packages/django/db/models/query.py", line 359, in aggregate
return query.get_aggregation(using=self.db)
File "~/env/local/lib/python2.7/site-packages/django/db/models/sql/query.py", line 389, in get_aggregation
result = query.get_compiler(using).execute_sql(SINGLE)
File "~/env/local/lib/python2.7/site-packages/django/db/models/sql/compiler.py", line 840, in execute_sql
cursor.execute(sql, params)
File "~/env/local/lib/python2.7/site-packages/django/db/backends/util.py", line 41, in execute
return self.cursor.execute(sql, params)
File "~/env/local/lib/python2.7/site-packages/django/db/backends/postgresql_psycopg2/base.py", line 58, in execute
six.reraise(utils.DatabaseError, utils.DatabaseError(*tuple(e.args)), sys.exc_info()[2])
File "~/env/local/lib/python2.7/site-packages/django/db/backends/postgresql_psycopg2/base.py", line 54, in execute
return self.cursor.execute(query, args)
DatabaseError: function avg(date) does not exist
LINE 1: SELECT AVG("games_game"."date") AS "date__avg" FROM "games_g...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
所以我嘗試了兩種解決方案,一個使用django querysets和python,第二個使用大多數原始SQL。
def compute_avg_date(self):
"""
Return the average date of the championship's game set.
Casts dates into time deltas, in order to perform a python mean.
"""
game_set = self.game_set.values_list('date', flat=True)
origin_date = datetime.date.min
try:
return (
sum(
map(lambda date: date-origin_date, game_set),
datetime.timedelta(0))/len(game_set) + origin_date)
except ZeroDivisionError:
return datetime.date.today()
def compute_avg_date_db(self):
"""
Does the same as above but directly in db operations.
"""
try:
return self.game_set.filter(week=week).extra(
select={
'avg_time': 'to_timestamp(avg(extract(epoch from date)))'
}).values_list(
'avg_time', flat=True)[0].date()
except AttributeError:
return datetime.date.today()
我以爲db-only版本會更快,所以我做了一點測試平臺。
>>> s = """\
... from championships.models import Championship
... champ = Championship.objects.get(pk=1)
... champ.compute_avg_date_db(10)
... """
>>> s1 = """\
... from championships.models import Championship
... champ = Championship.objects.get(pk=1)
... champ.compute_avg_date(10)
... """
>>> timeit.timeit(stmt=s, number=1000)
8.195073127746582
>>> timeit.timeit(stmt=s1, number=1000)
6.377335071563721
我做了一些其他類似的試驗中,全部都是示出該方法compute_avg_date,即使用Django查詢集和python該方法是比原始SQL方法稍快。我不是專家,所以如果有人能解釋它,歡迎發表評論。
你能舉個例子嗎? – karthikr
例子是goooood(代碼和輸出等) –