2012-04-21 50 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') 
相关问题