2009-09-03 99 views
1

我有一堆有一個值和日期字段對象:查詢基於數據/ Django的ORM

obj1 = Obj(date='2009-8-20', value=10) 
obj2 = Obj(date='2009-8-21', value=15) 
obj3 = Obj(date='2009-8-23', value=8) 

我想這回:

[10, 15, 0, 8] 

或更好,總的到這一點,合計:

[10, 25, 25, 33] 

我最好的辦法是直接從數據庫中獲取這個數據,但否則我使用forloop可以很輕鬆地完成總計。

我使用Django的ORM,也Postgres的

編輯:

只是要注意,我的例子只覆蓋了幾天,但在實踐中,我有上百個涵蓋了幾十年的對象。 ..我想要做的就是創建一個線圖顯示我的所有對象的總和如何在持續增長(很長的時間)

+0

數據庫?什麼數據庫?直到我們完成並在標籤中看到您使用的是Django(因此推測是它的內置ORM - 如果您使用的是另一種,您應該指定!),但這個問題非常混亂;未來,請將這些信息放在主題中或其他前面。我在這裏做了適當的編輯。 – 2009-09-03 03:51:49

+0

woops,對不起。是的,我正在使用django ORM,我也在使用Postgres – priestc 2009-09-03 04:46:04

+0

我們可以假設每個日期只有一個或零個對象嗎? – Wogan 2009-09-03 09:05:37

回答

4

這一個是沒有經過測試,因爲這是一個有點太痛苦成立一個Django表來測試:

from datetime import date, timedelta 
# http://www.ianlewis.org/en/python-date-range-iterator 
def datetimeRange(from_date, to_date=None): 
    while to_date is None or from_date <= to_date: 
     yield from_date 
     from_date = from_date + timedelta(days = 1) 

start = date(2009, 8, 20) 
end = date(2009, 8, 23) 
objects = Obj.objects.filter(date__gte=start) 
objects = objects.filter(date__lte=end) 

results = {} 
for o in objects: 
    results[o.date] = o.value 

return [results.get(day, 0) for day in datetimeRange(start, end)] 

這避免了運行,每天一個單獨的查詢。

+0

Django查詢集被懶惰地評估,所以你實際上最終每天都會運行一個單獨的查詢。 – David 2009-09-03 08:52:42

+1

除了這裏的查詢集只被評估一次,在for循環的開始,所以沒關係。 – Wogan 2009-09-03 09:03:54

+0

每次調用o.value時,都會觸及數據庫,因此每天都會觸擊數據庫。 – David 2009-09-03 09:10:42

0
result_list = [] 
for day in range(20,24):  
    result = Obj.objects.get(date=datetime(2009, 08, day)) 
    if result: 
     result_list.append(result.value) 
    else: 
     result_list.append(0) 
return result_list 

如果每個日期有一個以上的OBJ,你需要檢查len(obj)並在它超過1時迭代它們。

0

如果您循環訪問100次Obj.objects.get,則會執行100次SQL查詢。 Obj.objects.filter將在一個SQL查詢中返回結果,但您也選擇所有模型字段。這樣做的正確方法是使用Obj.objects.values_list,它將使用單個查詢來完成此操作,並僅選擇「值」字段。

start_date = date(2009, 8, 20) 
end_date = date(2009, 8, 23) 

objects = Obj.objects.filter(date__range=(start_date,end_date)) 
# values_list and 'value' aren't related. 'value' should be whatever field you're querying 
val_list = objects.values_list('value',flat=True) 
# val_list = [10, 15, 8] 

做val_list的運行聚合,你可以做到這一點(不能確定這是最Python的方式)

for i in xrange(len(val_list)): 
    if i > 0: 
     val_list[i] = val_list[i] + val_list[i-1] 

# val_list = [10,25,33] 

編輯:如果您需要考慮失蹤天,@Glenn Maynard的答案其實很不錯,儘管我更喜歡dict()語法:

objects = Obj.objects.filter(date__range=(start_date,end_date)).values('date','value') 
val_dict = dict((obj['date'],obj['value']) for obj in objects) 
# I'm stealing datetimeRange from @Glenn Maynard 
val_list = [val_dict.get(day, 0) for day in datetimeRange(start_date, end_date)] 
# val_list = [10,15,0,8] 
+0

此答案未能爲數據庫中不存在的天提供值。 – Wogan 2009-09-03 09:04:39

+1

-1對我的解決方案做出虛假陳述,然後給出與我完全相同的解決方案(但以不太清楚的方式)。 – 2009-09-03 19:00:40

+0

當我寫這篇文章的時候,我不清楚DB會缺少日期。你是對的,如果數據庫缺少日期,那麼你的解決方案是好的。 – David 2009-09-03 19:15:48