summaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorlufafajoshua <lufafajosh@gmail.com>2023-09-25 13:25:33 +0300
committerNatalia <124304+nessita@users.noreply.github.com>2023-10-11 16:10:30 -0300
commitd4bbdf5337089925f2900c44d3e953a947e4ca0e (patch)
tree2fb0c5cfe620d11e1e37221defadbbe7eebe1372 /docs
parent0bbe6ca2ac3d70e44081e54c235ff21568bf832c (diff)
[5.0.x] Fixed #34808 -- Doc'd aggregate function's default argument.
Backport of 8adc7c86ab85ed91e512bc49056e301cbe1715d0 from main
Diffstat (limited to 'docs')
-rw-r--r--docs/ref/models/querysets.txt18
-rw-r--r--docs/topics/db/aggregation.txt47
2 files changed, 55 insertions, 10 deletions
diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt
index 5c4760a868..fc1c5571e0 100644
--- a/docs/ref/models/querysets.txt
+++ b/docs/ref/models/querysets.txt
@@ -3910,7 +3910,8 @@ by the aggregate.
* Default alias: ``<field>__avg``
* Return type: ``float`` if input is ``int``, otherwise same as input
- field, or ``output_field`` if supplied
+ field, or ``output_field`` if supplied. If the queryset or grouping is
+ empty, ``default`` is returned.
.. attribute:: distinct
@@ -3948,7 +3949,8 @@ by the aggregate.
Returns the maximum value of the given expression.
* Default alias: ``<field>__max``
- * Return type: same as input field, or ``output_field`` if supplied
+ * Return type: same as input field, or ``output_field`` if supplied. If the
+ queryset or grouping is empty, ``default`` is returned.
``Min``
~~~~~~~
@@ -3958,7 +3960,8 @@ by the aggregate.
Returns the minimum value of the given expression.
* Default alias: ``<field>__min``
- * Return type: same as input field, or ``output_field`` if supplied
+ * Return type: same as input field, or ``output_field`` if supplied. If the
+ queryset or grouping is empty, ``default`` is returned.
``StdDev``
~~~~~~~~~~
@@ -3969,7 +3972,8 @@ by the aggregate.
* Default alias: ``<field>__stddev``
* Return type: ``float`` if input is ``int``, otherwise same as input
- field, or ``output_field`` if supplied
+ field, or ``output_field`` if supplied. If the queryset or grouping is
+ empty, ``default`` is returned.
.. attribute:: sample
@@ -3985,7 +3989,8 @@ by the aggregate.
Computes the sum of all values of the given expression.
* Default alias: ``<field>__sum``
- * Return type: same as input field, or ``output_field`` if supplied
+ * Return type: same as input field, or ``output_field`` if supplied. If the
+ queryset or grouping is empty, ``default`` is returned.
.. attribute:: distinct
@@ -4002,7 +4007,8 @@ by the aggregate.
* Default alias: ``<field>__variance``
* Return type: ``float`` if input is ``int``, otherwise same as input
- field, or ``output_field`` if supplied
+ field, or ``output_field`` if supplied. If the queryset or grouping is
+ empty, ``default`` is returned.
.. attribute:: sample
diff --git a/docs/topics/db/aggregation.txt b/docs/topics/db/aggregation.txt
index 3cb674aa95..9f98504c0c 100644
--- a/docs/topics/db/aggregation.txt
+++ b/docs/topics/db/aggregation.txt
@@ -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`.