Opened 10 years ago

Closed 10 years ago

#23669 closed Bug (fixed)

ProgrammingError when aggregating over an annotated & grouped ORM query

Reported by: Gregory Goltsov Owned by: nobody
Component: Database layer (models, ORM) Version: 1.6
Severity: Normal Keywords: orm, annotate, aggregate, values, avg, max
Cc: Triage Stage: Unreviewed
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Gregory Goltsov)

I have a simplified Django model:

class Module(models.Model):
    score = models.IntegerField()
    user = models.ForeignKey(User)

I was trying to construct a query to get the average highest score per module per user. In SQL, the query would look something like:

SELECT
    m.id
    AVG(max_score)
FROM
    (
        SELECT
            m.id
            Max(m.score) AS max_score
        FROM
            module m
        GROUP BY
            m.user_id,
            m.id
    ) f
GROUP BY
    m.id

In Django ORM the query looks like:

Module.objects.values(     # GROUP BY module_id, user_id
    'id', 'user'
).annotate(                # adding MAX(score) to the SELECT clause
    max_score=Max('score')
).aggregate(               # actually getting the average
    Avg('max_score')
)

This case is even documented in the docs: https://docs.djangoproject.com/en/1.6/topics/db/aggregation/#aggregating-annotations

However, upon evaluating, I encounter the following ProgrammingError:

ProgrammingError: syntax error at or near "FROM"
LINE 1: SELECT  FROM (SELECT

The ORM query looks like a perfectly normal query, no hacking, so I was really surprised to see this behaviour. Furthermore, I'm not the only one having this issue, dating as far as 2010:

Change History (5)

comment:1 by Gregory Goltsov, 10 years ago

Interestingly enough, in one of the questions someone hacked django.db.models.sql.query.BaseQuery internals to make the query work: it's in the Hacking Django section of the question from https://stackoverflow.com/questions/2558992/programmingerror-when-aggregating-over-an-annotated-grouped-django-orm-query

comment:2 by Gregory Goltsov, 10 years ago

Description: modified (diff)

comment:3 by Josh Smeaton, 10 years ago

I can't replicate this issue with Django 1.7. I do remember running into this about a year ago and I seem to remember it being fixed already. Which version of Django are you using?

comment:4 by Shai Berger, 10 years ago

I suspect you simplified the code too much -- since m.id is a primary key, there can only be one score value per id value; max(score) makes little sense.

More generally, you may note that the documentation example you linked to aggregates over sub-records, and you are trying to aggregate over the main record -- which, again, makes little sense when used via annotate rather than aggregate.

I have a strong suspicion that the hack mentioned will break "normal" annotate() calls (aggregating over sub-records).

comment:5 by Baptiste Mispelon, 10 years ago

Resolution: fixed
Status: newclosed

I can reproduce the reported issue in 1.6 but it's fixed in 1.7.

I traced the fix back to 4bd55547214ae149acadffe60536c379d51e318f.

Note: See TracTickets for help on using tickets.
Back to Top