Django aggregate query generating SQL error
I'm using Django 1.1.1 on a SQL Server 2005 db using the latest sqlserver_ado library.
models.py includes:
class Project(models.Model):
name = models.CharField(max_length=50)
class Thing(models.Model):
project = models.ForeignKey(Project)
reference = models.CharField(max_length=50)
class ThingMonth(models.Model):
thing = models.ForeignKey(Thing)
timestamp = models.DateTimeField()
ThingMonthValue = models.FloatField()
class Meta:
db_table = u'ThingMonthSummary'
In a view, I have retrieved a queryset called 'things' which contains 25 Things:
things = Thing.objects.select_related().filter(project=1).order_by('reference')
I then want to do an aggregate query to get the average ThingMonthValue for the first 20 of those Things for a certain period, and the same value for the last 5.
For the first 20 I do:
averageThingMonthValue = ThingMonth.objects.filter(thing__in=things[:20],timestamp__range="2009-01-01 00:00","2010-03-00:00")).aggregate(Avg('ThingMonthValue'))['ThingMonthValue__avg']
This works fine, and returns the desired value.
For the last 5 I do:
averageThingMonthValue = ThingMonth.objects.filter(thing__in=things[20:],timestamp__range="2009-01-01 00:00","2010-03-00:00")).aggregate(Avg('ThingMonthValue'))['ThingMonthValue__avg']
But for this I get an SQL error: 'Only one expression can be specified in the select list when the subquery is not introduced with EXISTS.'
The SQL query being used by django reads:
SELECT AVG([ThingMonthSummary].[ThingMonthValue]) AS [ThingMonthValue__avg]
FROM [ThingMonthSummary]
WHERE ([ThingMonthSummary].[thing_id] IN
(SELECT _row_num, [id] FROM ( SELECT ROW_NUMBER() OVER ( ORDER BY [AAAA].[id] ASC) as _row_num,
[AAAA].[id] FROM ( SELECT U0.[id] FROM [Thing] U0 WHERE U0.[project_id] = 1 ) AS [AAAA]) as QQQ
where 20 < _row_num) AND [ThingMonthSummary].[timestamp] BETWEEN '01/01/09 00:00:00' and '03/01/10 00:00:00')
Any idea why it works for one slice of the Things and not the s开发者_JAVA百科econd? I've checked and the two slices do contain the desired Things correctly.
This looks like a bug in the SQL generator of the Django ORM. The generated SQL is returning _row_num
as well as id
in the IN
subquery of the second query when it isn't required.
This wouldn't be needed for the first 20 calculation, since the subquery could be written as SELECT TOP 20...
To get around this for last n rows calculations, you could return the un-aggregated collection of Things
and carry out the average calculation in code.
(There may be another Django-specific solution, but I'm a SQL server guy.)
精彩评论