So, I have a model that looks like this:
class Names(models.Model):
name = models.CharField()
class Entries(models.Model):
name = models.ForeignKey(Names)
date = models.DateField()
The data looks something like this
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
I want to query Entries with a date, and get each name record once where it is less than or equal to the date. So, I want this returned if I query with date 2011-06-01:
name_1 | 2011-06-01
name_2 | 2011-03-01
name_3 | 2011-02-01
name_4 | 2009-07-01
My assumption is this would do the trick:
date = datetime(year=2011, month=06, day=01)
results = Entries.objects.filter(date__lte=date).order_by('date').distinct('name')
But, I keep getting duplicate name entries in there.
Any tips, friends?
Edit: The solution was provided by Gareth Rees. I had to modify it slightly, but it looks like this:
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'))
Here are a couple of approaches, depending on how you need the results.
(1) If you don’t mind getting the results in dictionary form (rather than
Entriesobjects) then you can useannotatecombined withvaluesto group the results. In this case the query you want would be something like this:(2) If you need to get the results back as
Entriesobjects, then you can useextrato pick only entries which are the earliest among all entries with the same name: