2012-04-21 55 views
2

所以,我有一個模型,看起來像這樣的日期不同的條目的查詢集:獲取具有儘可能接近要使用Django

class Names(models.Model): 
    name = models.CharField() 

class Entries(models.Model): 
    name = models.ForeignKey(Names) 
    date = models.DateField() 

的數據看起來是這樣

name | date 

name_1 | 2011-06-01 
name_2 | 2011-03-01 
name_3 | 2011-02-01 
name_1 | 2010-06-01 
name_2 | 2010-03-02 
name_3 | 2010-02-01 
name_4 | 2009-07-01 

我想要查詢具有日期的條目,並且獲得每個名稱記錄一次其中它是小於或等於到日期。所以,我想這回,如果我有時間2011-06-01查詢:

name_1 | 2011-06-01 
name_2 | 2011-03-01 
name_3 | 2011-02-01 
name_4 | 2009-07-01 

我的假設是,這將這樣的伎倆:

date = datetime(year=2011, month=06, day=01) 
results = Entries.objects.filter(date__lte=date).order_by('date').distinct('name') 

不過,我不斷收到重複的名稱項在那裏。

任何提示,朋友?

編輯:該解決方案由Gareth Rees提供。我只好稍微修改它,但它看起來是這樣的:

sql = """myapp_entries.id = (SELECT E.id from myapp_entries AS E 
          WHERE E.name_id = myapp_names.id AND 
          '"""+date.strftime('%Y-%m-%d')+"""' 
          ORDER BY E.date DESC 
          LIMIT 1)''' 

results = (Entries.objects 
      .extra(where = [sql]) 
      .filter(date__lte = date) 
      .order_by('name', 'date')) 
+0

隨着數據(NAME_1,2011-06-01),(NAME_1,2011-06-02)用 '2011-06-02' 日期篩選時,什麼是預期收益爲你? – 2012-04-21 11:29:10

+0

Gareth解決了這個問題,但在回答你的問題時,日期應該小於或等於如此:** 2011-06-02 ** – lextoumbourou 2012-04-22 02:30:45

回答

1

這裏有幾個方法,這取決於你如何需要的結果。 (1)如果您不介意以字典形式(而不是Entries對象)獲得結果,則可以使用annotatevalues結合對結果進行分組。在這種情況下你想要的查詢將是這樣的:

from django.db.models import Min 
results = (Entries.objects 
      .filter(date__lte = date) 
      .values('name') 
      .annotate(date = Min('date')) 
      .order_by('name', 'date')) 

(2)如果你需要得到的結果早在Entries對象,那麼你可以使用extra挑選僅是在所有的最早的條目具有相同名稱的條目:

sql = '''id = (SELECT E.id FROM myapp_entries AS E 
       WHERE E.name_id = myapp_entries.name_id 
       ORDER BY E.date 
       LIMIT 1)''' 
results = (Entries.objects 
      .extra(where = [sql]) 
      .filter(date__lte = date) 
      .order_by('name', 'date')) 
+0

Gareth,你真的很出色。實際上,我確實需要它作爲Entries對象,所以我使用了選項2.我在SQL語法中更改了2個東西以使其起作用。首先是使id聲明不那麼模糊,其次是指定一個DESC命令。不幸的是,我仍然不完全明白它爲什麼起作用。我需要再考慮一下。非常感謝。 'myapp_entries.id =(從myapp_entries選擇E.id爲E WHERE E.name_id = myapp_names.id ORDER BY E.date DESC LIMIT 1)' – lextoumbourou 2012-04-22 02:28:14

+0

你們可以請解釋(2)不會做什麼辦法與我的解決方案不同還是更好?我相當確定次選不是最好的表現明智的... 特別是因爲揭幕戰顯然沒有嘗試我的。 – 2012-04-22 10:36:57

+0

它適用於MySQL。 (是的,子選擇可能表現不佳,這就是爲什麼我先把選項(1)。) – 2012-04-22 11:17:45

0

嘗試使用.distinct(「name__name」),因爲你想穿越外鍵。

+0

不幸的是,我已經嘗試過了。沒有骰子,寶貝。非常感謝你,如果你甚至需要幫助搬家,請告訴我。 ** Entries.objects.filter(date__lte = date).order_by('date')。distinct('name__name')** > [<條目:name_4 2009-07-01>,<條目:name_3 2010-02-01>,<條目:name_2 2010-03-01>,<條目:name_1 2010- 06-01>,<條目:name_3 2011-02-01>,<條目:name_2 2011-03-01>,<條目:name_1 2011-06-01>]' – lextoumbourou 2012-04-21 08:35:36

0

你應該閱讀文檔:https://docs.djangoproject.com/en/dev/ref/models/querysets/#distinct

.distinct(*域)僅適用於Postgres的,並需要您.order_by匹配和.distinct,如:

results = Entries.objects.filter(date__lte=date).order_by('date').distinct('date') 

所以你的情況它最有可能是這樣的:

results = Entries.objects.filter(date__lte=date).order_by('name', 'date').distinct('name') 
相關問題