I am trying to do something very similar to: Annotate Custom SQL Function (similar to date_trunc) to Django ORM Queryset
but have found the solution to be inadequate.
Using the same example as found in the prior link, suppose we have a Django model as such.
class Measurement(models.Model):
device_id = models.IntegerField(primary_key=True)
time = models.DateTimeField()
s0 = models.FloatField(blank=True, null=True)
s1 = models.FloatField(blank=True, null=True)
We are trying to leverage the following in the ORM.
SELECT
time_bucket('1 minute', time) AS tb,
AVG(s0)
FROM measurements
WHERE
time >= to_timestamp(1) AND
time <= to_timestamp(2)
GROUP BY tb
ORDER BY tb ASC;
We have a successful custom function as such:
class TimeBucket(Func):
function = 'time_bucket'
template = '%(function)s(\'{bucket_width}\', %(expressions)s)'.format(bucket_width='1 minute')
But we see that running a query like the following:
qs = (
Measurement.objects
.filter(...)
.annotate(tb=TimeBucket('time'))
.values('tb')
.annotate(s_desc=Avg('s0'))
.order_by('tb')
)
and checking its corresponding qs.query
will always include time
in the GROUP BY query. I only want to group by tb
, the derived value, as shown in the original SQL. From what I'm reading, you need only use values('tb')
as we are doing above to group by tb
, but Django seems to append on time
for some reason. Why is this the case?
Is it possible that my problem is less with this external function and more that I'm trying to group by a calculated field?