aggregate() - generate summary values over an entire
QuerySet
annotate() - genarate an independent summary for
each object in a QuerySet
Syntax for both aggregate() and
annotate() is the same.
aggregate() is a terminal clause
for a QuerySet that, when invoked, returns a dictionary of name-value
pairs, the name is an identifier for the aggregate value; the value is
the computed aggregate.
when developing a complex query that involves both
annotate() and filter() clauses pay particular
attention to the order in which the clauses are applied to the QuerySet.
When an annotate() clause is applied to a query, the
annotation is computed over the state of the query up to the point where
the annotation is requested. The practical implication of this is that
filter() and annotate() are not
commutative operations.
SQL groupby can be done by values() +
annotate(): when a values() clause is used to
constrain the columns, the results are grouped according to the unique
combinations of the fields specified in the values()
clause. An annotation is then provided for each unique group; the
annotation is computed over all members of the group. As with
filter() clause, the order in which annotate()
and values() clauses are applied to a query is
significant.
Tips:
print(queryset.query) to see the SQL queryqueryset.explain() to do SQL explain of a query