Агрегатный запрос Django, генерирующий ошибку SQL - PullRequest
0 голосов
/ 23 апреля 2010

Я использую Django 1.1.1 на базе данных SQL Server 2005 с использованием новейшей библиотеки sqlserver_ado.

models.py включает в себя:

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'

В представлении я получил набор запросов, называемый «вещи», который содержит 25 вещей:

things = Thing.objects.select_related().filter(project=1).order_by('reference')

Затем я хочу сделать агрегированный запрос, чтобы получить среднее значение ThingMonthValue для первых 20 из этих вещей за определенный период и то же значение для последних 5.

Для первых 20 я делаю:

averageThingMonthValue = ThingMonth.objects.filter(thing__in=things[:20],timestamp__range="2009-01-01 00:00","2010-03-00:00")).aggregate(Avg('ThingMonthValue'))['ThingMonthValue__avg']

Это отлично работает и возвращает желаемое значение.

За последние 5 я делаю:

averageThingMonthValue = ThingMonth.objects.filter(thing__in=things[20:],timestamp__range="2009-01-01 00:00","2010-03-00:00")).aggregate(Avg('ThingMonthValue'))['ThingMonthValue__avg']

Но для этого я получаю ошибку SQL: «В списке выбора можно указать только одно выражение, если подзапрос не введен с EXISTS.»

SQL-запрос, используемый django, читает:

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')

Есть идеи, почему это работает для одного кусочка вещей, а не для второго? Я проверил, и два ломтика правильно содержат нужные вещи.

1 Ответ

2 голосов
/ 23 апреля 2010

Это похоже на ошибку в генераторе SQL в Django ORM. Сгенерированный SQL возвращает _row_num, а также id в подзапросе IN второго запроса, когда он не требуется.

Это не понадобится для первых 20 вычислений, так как подзапрос может быть записан как SELECT TOP 20...

Чтобы обойти это для последних вычислений n строк, вы можете вернуть неагрегированный набор Things и выполнить среднее вычисление в коде.

(Может быть другое решение, специфичное для Django, но я парень с SQL-сервером.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...