summaryrefslogtreecommitdiff
path: root/django/db/models/sql
diff options
context:
space:
mode:
Diffstat (limited to 'django/db/models/sql')
-rw-r--r--django/db/models/sql/compiler.py16
1 files changed, 12 insertions, 4 deletions
diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py
index 002bc05824..7ea9ef9067 100644
--- a/django/db/models/sql/compiler.py
+++ b/django/db/models/sql/compiler.py
@@ -136,10 +136,7 @@ class SQLCompiler(object):
# If the DB can group by primary key, then group by the primary key of
# query's main model. Note that for PostgreSQL the GROUP BY clause must
# include the primary key of every table, but for MySQL it is enough to
- # have the main table's primary key. Currently only the MySQL form is
- # implemented.
- # MySQLism: however, columns in HAVING clause must be added to the
- # GROUP BY.
+ # have the main table's primary key.
if self.connection.features.allows_group_by_pk:
# The logic here is: if the main model's primary key is in the
# query, then set new_expressions to that field. If that happens,
@@ -150,7 +147,18 @@ class SQLCompiler(object):
getattr(expr.output_field, 'model') == self.query.model):
pk = expr
if pk:
+ # MySQLism: Columns in HAVING clause must be added to the GROUP BY.
expressions = [pk] + [expr for expr in expressions if expr in having]
+ elif self.connection.features.allows_group_by_selected_pks:
+ # Filter out all expressions associated with a table's primary key
+ # present in the grouped columns. This is done by identifying all
+ # tables that have their primary key included in the grouped
+ # columns and removing non-primary key columns referring to them.
+ pks = {expr for expr in expressions if hasattr(expr, 'target') and expr.target.primary_key}
+ aliases = {expr.alias for expr in pks}
+ expressions = [
+ expr for expr in expressions if expr in pks or getattr(expr, 'alias', None) not in aliases
+ ]
return expressions
def get_select(self):