#12886 closed Bug (fixed)
.aggregate() does not honour sliced queryset
Reported by: | Owned by: | ||
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.4 |
Severity: | Normal | Keywords: | aggregate |
Cc: | 3point2, Filip Gruszczyński | Triage Stage: | Accepted |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
If I aggregate a sliced queryset, the result is an aggregate across the whole unsliced queryset:
In [97]: qs = Encounter.objects.all() In [98]: qs.aggregate(**aggregations) Out[98]: {'total_no_of_adults': 19, 'total_no_of_children': 8, 'total_no_of_dogs': 2} In [99]: qs[0:5].aggregate(**aggregations) Out[99]: {'total_no_of_adults': 19, 'total_no_of_children': 8, 'total_no_of_dogs': 2}
It works though if .annotate() is called first, even if no annotations are given:
In [100]: qs[0:5].annotate().aggregate(**aggregations) Out[100]: {'total_no_of_adults': 8, 'total_no_of_children': 8, 'total_no_of_dogs': 2}
The latter are the correct figures for my example model.
Attachments (1)
Change History (18)
comment:1 by , 15 years ago
Component: | Database layer (models, ORM) → ORM aggregation |
---|---|
Owner: | removed |
comment:2 by , 15 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:3 by , 14 years ago
Cc: | added |
---|
comment:4 by , 14 years ago
I have managed to patch this, but encountered larger problem, that I have problems with. I have added following test to modeltests/aggregation/tests.py:
def test_join_annotate_aggregate(self): vals = Book.objects.all().annotate().aggregate(Max("authors__age")) self.assertEqual(len(vals), 1) self.assertEqual(vals["authors__age__max"], 57)
and it causes following exception:
====================================================================== ERROR: test_join_annotate_aggregate (modeltests.aggregation.tests.BaseAggregateTestCase) ---------------------------------------------------------------------- Traceback (most recent call last): File "/home/gruszczy/Programy/django/tests/modeltests/aggregation/tests.py", line 21, in test_join_annotate_aggregate vals = Book.objects.all().annotate().aggregate(Max("authors__age")) File "/home/gruszczy/Programy/django/django/db/models/query.py", line 312, in aggregate return query.get_aggregation(using=self.db) File "/home/gruszczy/Programy/django/django/db/models/sql/query.py", line 366, in get_aggregation result = query.get_compiler(using).execute_sql(SINGLE) File "/home/gruszczy/Programy/django/django/db/models/sql/compiler.py", line 729, in execute_sql cursor.execute(sql, params) File "/home/gruszczy/Programy/django/django/db/backends/sqlite3/base.py", line 200, in execute return Database.Cursor.execute(self, query, params) DatabaseError: no such column: T5.age
Generated SQL looks like this:
SELECT "aggregation_book"."id" AS "id", "aggregation_book"."isbn" AS "isbn", "aggregation_book"."name" AS "name", "aggregation_book"."pages" AS "pages", "aggregation_book"."rating" AS "rating", "aggregation_book"."price" AS "price", "aggregation_book"."contact_id" AS "contact_id", "aggregation_book"."publisher_id" AS "publisher_id", "aggregation_book"."pubdate" AS "pubdate" FROM "aggregation_book" LEFT OUTER JOIN "aggregation_book_authors" ON ("aggregation_book"."id" = "aggregation_book_authors"."book_id") LEFT OUTER JOIN "aggregation_author" T5 ON ("aggregation_book_authors"."author_id" = T5."id") GROUP BY "aggregation_book"."id", "aggregation_book"."isbn", "aggregation_book"."name", "aggregation_book"."pages", "aggregation_book"."rating", "aggregation_book"."price", "aggregation_book"."contact_id", "aggregation_book"."publisher_id", "aggregation_book"."pubdate"
I am posting my partial patch with tests, so maybe someone could direct me, where I should go from here and how can I solve the encountered bug.
comment:5 by , 14 years ago
Cc: | added |
---|
comment:6 by , 14 years ago
Type: | → Bug |
---|
comment:7 by , 14 years ago
Severity: | → Normal |
---|
comment:10 by , 12 years ago
Version: | 1.2-beta → 1.4 |
---|
This seems like a fairly significant limitation. As far as I can see, I cannot have the database perform aggregate functions on queries with LIMIT clauses, e.g. "show me the max date for the top 100 results matching this WHERE clause". This caveat should at least be called out in the documentation, since it otherwise implies that slices and aggregates should work without issue.
comment:11 by , 12 years ago
Component: | ORM aggregation → Database layer (models, ORM) |
---|
comment:12 by , 12 years ago
Keywords: | aggregate added |
---|
comment:13 by , 11 years ago
Owner: | set to |
---|---|
Resolution: | → fixed |
Status: | new → closed |
comment:14 by , 11 years ago
This bug still exists. I am using Django 1.6 on Python 2.6 and both Sum and Avg use the entire query set instead of the sliced query set. Threw in an annotate() as mentioned and this fixed it all up. Someone should open this up again, it has NOT been fixed!
comment:17 by , 10 years ago
Note: the fix here *does* fix #15101 (django.contrib.gis' "Extent" aggregate had the same issue).
I've also just discovered this issue (using the Sum aggregate) and did some poking around: get_aggregate in source:django/trunk/django/db/models/sql/query.py calls query.clear_limits(). With this line commented out, a query like this is issued:
which seems correct. unfortunately the DB (in my case sqlite) ignores the limit for the sum aggregate anyway.
For this to work right, the sql issued will have to look something like
in other words, grab the SQL from the query as if it wasn't an aggregate, and then nest it inside the aggregation function.