Problem/Motivation
Adding a having condition is necessary for placing conditions on fields created via subqueries. For example creating a custom view field plugin with the following section of code:
$this->query->addField(
'',
"(
SELECT COUNT(t.field)
FROM table t
WHERE t.field = $this->tableAlias.field
)",
'custom_field_name',
[]
);
Now because the field is not part of a table, it cannot be filtered in the 'WHERE' clause of the query, thus a condition is needed in the 'HAVE' clause.
But calling $this->query->addHavingExpression() also adds a 'GROUP BY' clause to the query because of this code:
$this->hasAggregate = FALSE;
$non_aggregates = $this->getNonAggregates();
if (count($this->having)) {
$this->hasAggregate = TRUE;
}
elseif (!$this->hasAggregate) {
// Allow 'GROUP BY' even no aggregation function has been set.
$this->hasAggregate = $this->view->display_handler->getOption('group_by');
}
$groupby = [];
if ($this->hasAggregate && (!empty($this->groupby) || !empty($non_aggregates))) {
$groupby = array_unique(array_merge($this->groupby, $non_aggregates));
}
And if the view does not explicitly use aggregation, an error is thrown because the sorting fields are not taken into consideration as non-aggreagets by the getNonAggregates() method.
Thrown error:
Drupal\Core\Database\DatabaseExceptionWrapper: Exception in Workbench: Recent content[workbench_recent_content]: SQLSTATE[42000]: Syntax error or access violation: 1055 Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated column 'node_field_data.changed' which is not functionally dependent on columns in GROUP BY clause;
Also, as a curiosity, why is aggregation forced when adding 'HAVE' clauses?
Proposed resolution
Change the method Drupal\views\Plugin\views\query\Sql::getNonAggregates() to also take into consideration the 'ORDER BY' fields:
foreach ($this->fields + $this->orderby as $field) {