所以,我有一个看起来像这样的模型:
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 :(得分:1)
以下是一些方法,具体取决于您需要的结果。
(1)如果您不介意以字典形式(而非Entries
个对象)获取结果,则可以使用annotate
与values
结合对结果进行分组。在这种情况下,您想要的查询将是这样的:
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'))
答案 1 :(得分:0)
尝试使用.distinct('name__name'),因为您想要遍历外键。
答案 2 :(得分: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')