Author: mtredinnick Date: 2009-03-25 04:05:38 -0500 (Wed, 25 Mar 2009) New Revision: 10172
Modified: django/trunk/docs/ref/models/querysets.txt django/trunk/docs/topics/db/aggregation.txt Log: Fixed #10574 -- Documented interaction between annotations and order_by. In the future, I'd like to fix this properly, but the current behavior has the advantage of being consistent across the board (and changing it everywhere is backwards-incompatible with documented functionality). Modified: django/trunk/docs/ref/models/querysets.txt =================================================================== --- django/trunk/docs/ref/models/querysets.txt 2009-03-25 08:28:57 UTC (rev 10171) +++ django/trunk/docs/ref/models/querysets.txt 2009-03-25 09:05:38 UTC (rev 10172) @@ -296,6 +296,8 @@ ordering was undefined prior to calling ``reverse()``, and will remain undefined afterward). +.. _querysets-distinct: + ``distinct()`` ~~~~~~~~~~~~~~ Modified: django/trunk/docs/topics/db/aggregation.txt =================================================================== --- django/trunk/docs/topics/db/aggregation.txt 2009-03-25 08:28:57 UTC (rev 10171) +++ django/trunk/docs/topics/db/aggregation.txt 2009-03-25 09:05:38 UTC (rev 10172) @@ -315,6 +315,57 @@ clause is applied after the ``annotate()`` clause, you need to explicitly include the aggregate column. +Interaction with default ordering or ``order_by()`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Fields that are mentioned in the ``order_by()`` part of a queryset (or which +are used in the default ordering on a model) are used when selecting the +output data, even if they are not otherwise specified in the ``values()`` +call. These extra fields are used to group "like" results together and they +can make otherwise identical result rows appear to be separate. This shows up, +particularly, when counting things. + +By way of example, suppose you have a model like this:: + + class Item(models.Model): + name = models.CharField(max_length=10) + data = models.IntegerField() + + class Meta: + ordering = ["name"] + +The important part here is the default ordering on the ``name`` field. If you +want to count how many times each distinct ``data`` value appears, you might +try this:: + + # Warning: not quite correct! + Item.objects.values("data").annotate(Count("id")) + +...which will group the ``Item`` objects by their common ``data`` values and +then count the number of ``id`` values in each group. Except that it won't +quite work. The default ordering by ``name`` will also play a part in the +grouping, so this query will group by distinct ``(data, name)`` pairs, which +isn't what you want. Instead, you should construct this queryset:: + + Item.objects.values("data").annotate(Count("id")).order_by() + +...clearing any ordering in the query. You could also order by, say, ``data`` +without any harmful effects, since that is already playing a role in the +query. + +This behavior is the same as that noted in the queryset documentation for +:ref:`distinct() <querysets-distinct>` and the general rule is the same: +normally you won't want extra columns playing a part in the result, so clear +out the ordering, or at least make sure it's restricted only to those fields +you also select in a ``values()`` call. + +.. note:: + You might reasonably ask why Django doesn't remove the extraneous columns + for you. The main reason is consistency with ``distinct()`` and other + places: Django **never** removes ordering constraints that you have + specified (and we can't change those other methods' behavior, as that + would violate our :ref:`misc-api-stability` policy). + Aggregating annotations ----------------------- --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django updates" group. To post to this group, send email to django-updates@googlegroups.com To unsubscribe from this group, send email to django-updates+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-updates?hl=en -~----------~----~----~----~------~----~------~--~---