|
@@ -184,17 +184,39 @@ of the ``annotate()`` clause is a ``QuerySet``; this ``QuerySet`` can be
|
|
|
modified using any other ``QuerySet`` operation, including ``filter()``,
|
|
|
``order_by()``, or even additional calls to ``annotate()``.
|
|
|
|
|
|
+Combining multiple aggregations
|
|
|
+-------------------------------
|
|
|
+
|
|
|
+Combining multiple aggregations with ``annotate()`` will `yield the wrong
|
|
|
+results <https://code.djangoproject.com/ticket/10060>`_, as multiple tables are
|
|
|
+cross joined. Due to the use of ``LEFT OUTER JOIN``, duplicate records will be
|
|
|
+generated if some of the joined tables contain more records than the others:
|
|
|
+
|
|
|
+ >>> Book.objects.first().authors.count()
|
|
|
+ 2
|
|
|
+ >>> Book.objects.first().chapters.count()
|
|
|
+ 3
|
|
|
+ >>> q = Book.objects.annotate(Count('authors'), Count('chapters'))
|
|
|
+ >>> q[0].authors__count
|
|
|
+ 6
|
|
|
+ >>> q[0].chapters__count
|
|
|
+ 6
|
|
|
+
|
|
|
+For most aggregates, there is no way to avoid this problem, however, the
|
|
|
+:class:`~django.db.models.Count` aggregate has a ``distinct`` parameter that
|
|
|
+may help:
|
|
|
+
|
|
|
+ >>> q = Book.objects.annotate(Count('authors', distinct=True), Count('chapters', distinct=True))
|
|
|
+ >>> q[0].authors__count
|
|
|
+ 2
|
|
|
+ >>> q[0].chapters__count
|
|
|
+ 3
|
|
|
+
|
|
|
.. admonition:: If in doubt, inspect the SQL query!
|
|
|
|
|
|
In order to understand what happens in your query, consider inspecting the
|
|
|
``query`` property of your ``QuerySet``.
|
|
|
|
|
|
- For instance, combining multiple aggregations with ``annotate()`` will
|
|
|
- yield the wrong results, as `multiple tables are cross joined`_,
|
|
|
- resulting in duplicate row aggregations.
|
|
|
-
|
|
|
-.. _multiple tables are cross joined: https://code.djangoproject.com/ticket/10060
|
|
|
-
|
|
|
Joins and aggregates
|
|
|
====================
|
|
|
|