Skip to content

Instantly share code, notes, and snippets.

@carljm
Created August 21, 2014 20:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save carljm/dcd7cc6d4b39ed343221 to your computer and use it in GitHub Desktop.
Save carljm/dcd7cc6d4b39ed343221 to your computer and use it in GitHub Desktop.
GREATEST() of aggregates, in the Django ORM.
class Greatest(object):
"""A pseudo- (or meta-) aggregate; returns highest of sub-aggregates.
This has to be inserted directly into the Query internals; it can't go
through the usual ``qs.annotate(...)`` or ``qs.aggregate(...)`` path
(because that leads to ``Query.add_aggregate(...)`` which makes assumptions
we can't meet).
To use, instantiate ``Greatest`` with one or more normal aggregates, and
call ``greatest_instance.add_to_qs(queryset, 'name')``
All aggregates passed to ``Greatest`` must be based on the same underlying
database field type (i.e. char, int, datetime, whatever), or else things
will probably explode.
"""
is_ordinal = False
is_computed = False
def __init__(self, *aggregates):
self.aggregates = aggregates
self.sql_aggregates = []
def add_to_qs(self, queryset, alias):
"""Add to the nominated queryset."""
for aggregate in self.aggregates:
queryset.query.add_aggregate(
aggregate, queryset.model, 'tmpalias', False)
self.sql_aggregates.append(
queryset.query.aggregates.pop('tmpalias'))
queryset._setup_aggregate_query([alias])
queryset.query.aggregates[alias] = self
@cached_property
def field(self):
return self.sql_aggregates[0].field
def as_sql(self, qn, connection):
sql_bits = []
params = []
for a in self.sql_aggregates:
sql, p = a.as_sql(qn, connection)
sql_bits.append(sql)
params.extend(p)
return "GREATEST(%s)" % (', '.join(sql_bits)), params
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment