2

所以,我有一个看起来像这样的模型:

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'))
4

3 回答 3

1

以下是几种方法,具体取决于您对结果的需要。

(1) 如果您不介意以字典形式(而不是Entries对象)获取结果,则可以使用annotate组合 withvalues对结果进行分组。在这种情况下,您想要的查询将是这样的:

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'))
于 2012-04-21T13:49:59.667 回答
0

尝试使用 .distinct('name__name') 因为您想要遍历外键。

于 2012-04-21T08:00:48.563 回答
0

您可能应该阅读文档:https ://docs.djangoproject.com/en/dev/ref/models/querysets/#distinct

.distinct(*fields) 仅适用于 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')
于 2012-04-21T08:17:06.790 回答