Say I have the following data:
| id | user_id | time |
| 1 | 1 | 10.0 |
| 2 | 1 | 12.0 |
| 3 | 2 | 11.0 |
| 4 | 2 | 13.0 |
What I want is to query this table such that I get the MIN(time) per user_id:
| id | user_id | time |
| 1 | 1 | 10.0 |
| 3 | 2 | 11.0 |
So my SQL would like this:
SELECT id, user_id, time FROM table GROUP BY user_id HAVING MIN(time)
However, when trying to use .annotate(Min('time')), Django will GROUP BY on arbitrary (wrong) fields. For example see the following code and the resulting (simplified) SQL:
>>> Table.objects.annotate(Min('time')).query
SELECT id, user_id, time, MIN(time) FROM table GROUP BY id, user_id, time
>>> Table.objects.values('id', 'time').annotate(Min('time')).query
SELECT id, time, MIN(time) FROM table GROUP BY id, time
The resulting SQL is far from my desired output. I’m currently working around this by using raw SQL, however this defeats the purpose of using an ORM in the first place. Also, the resulting code is difficult to reuse as normal .filter() cannot be applied.
There are similar questions about this type of querying, however they are rather old and do not incorporate changes to Django since 1.3.
It’s not pretty code but. Using django’s ‘extra’ queryset method and where as an argument you can achieve getting back the desired result set. i.e.