diff options
| author | lufafajoshua <lufafajosh@gmail.com> | 2023-09-25 13:25:33 +0300 |
|---|---|---|
| committer | Natalia <124304+nessita@users.noreply.github.com> | 2023-10-11 16:11:09 -0300 |
| commit | e8fe48d3a02dbe3b57a87b334f6335b701f0306d (patch) | |
| tree | 8c2ebf2cbc0be14ec846708d15dafd2ea30a5fdc /docs/topics | |
| parent | 830990fa6ca4a76489ce6c943fce3fd0123a449f (diff) | |
[4.2.x] Fixed #34808 -- Doc'd aggregate function's default argument.
Backport of 8adc7c86ab85ed91e512bc49056e301cbe1715d0 from main
Diffstat (limited to 'docs/topics')
| -rw-r--r-- | docs/topics/db/aggregation.txt | 47 |
1 files changed, 43 insertions, 4 deletions
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`. |
