|
@@ -60,14 +60,16 @@ above:
|
|
|
>>> Book.objects.filter(publisher__name="BaloneyPress").count()
|
|
|
73
|
|
|
|
|
|
- # Average price across all books.
|
|
|
+ # Average price across all books, provide default to be returned instead
|
|
|
+ # of None if no books exist.
|
|
|
>>> from django.db.models import Avg
|
|
|
- >>> Book.objects.aggregate(Avg("price"))
|
|
|
+ >>> Book.objects.aggregate(Avg("price", default=0))
|
|
|
{'price__avg': 34.35}
|
|
|
|
|
|
- # Max price across all books.
|
|
|
+ # Max price across all books, provide default to be returned instead of
|
|
|
+ # None if no books exist.
|
|
|
>>> from django.db.models import Max
|
|
|
- >>> Book.objects.aggregate(Max("price"))
|
|
|
+ >>> Book.objects.aggregate(Max("price", default=0))
|
|
|
{'price__max': Decimal('81.20')}
|
|
|
|
|
|
# Difference between the highest priced book and the average price of all books.
|
|
@@ -632,3 +634,40 @@ aggregate that author count, referencing the annotation field:
|
|
|
>>> from django.db.models import Avg, Count
|
|
|
>>> Book.objects.annotate(num_authors=Count("authors")).aggregate(Avg("num_authors"))
|
|
|
{'num_authors__avg': 1.66}
|
|
|
+
|
|
|
+Aggregating on empty querysets or groups
|
|
|
+----------------------------------------
|
|
|
+
|
|
|
+When an aggregation is applied to an empty queryset or grouping, the result
|
|
|
+defaults to its :ref:`default <aggregate-default>` parameter, typically
|
|
|
+``None``. This behavior occurs because aggregate functions return ``NULL`` when
|
|
|
+the executed query returns no rows.
|
|
|
+
|
|
|
+You can specify a return value by providing the :ref:`default
|
|
|
+<aggregate-default>` argument for most aggregations. However, since
|
|
|
+:class:`~django.db.models.Count` does not support the :ref:`default
|
|
|
+<aggregate-default>` argument, it will always return ``0`` for empty querysets
|
|
|
+or groups.
|
|
|
+
|
|
|
+For example, assuming that no book contains *web* in its name, calculating the
|
|
|
+total price for this book set would return ``None`` since there are no matching
|
|
|
+rows to compute the :class:`~django.db.models.Sum` aggregation on:
|
|
|
+
|
|
|
+.. code-block:: pycon
|
|
|
+
|
|
|
+ >>> from django.db.models import Sum
|
|
|
+ >>> Book.objects.filter(name__contains="web").aggregate(Sum("price"))
|
|
|
+ {"price__sum": None}
|
|
|
+
|
|
|
+However, the :ref:`default <aggregate-default>` argument can be set when
|
|
|
+calling :class:`~django.db.models.Sum` to return a different default value if
|
|
|
+no books can be found:
|
|
|
+
|
|
|
+.. code-block:: pycon
|
|
|
+
|
|
|
+ >>> Book.objects.filter(name__contains="web").aggregate(Sum("price", default=0))
|
|
|
+ {"price__sum": Decimal("0")}
|
|
|
+
|
|
|
+Under the hood, the :ref:`default <aggregate-default>` argument is implemented
|
|
|
+by wrapping the aggregate function with
|
|
|
+:class:`~django.db.models.functions.Coalesce`.
|