Bug #121672 HAVING without GROUP BY does not create the single aggregate group described in the SELECT documentation
Description:
MySQL Community Server 9.7.1 accepts a SELECT with HAVING and no GROUP BY, but does not form an implicit aggregate group when the query contains no aggregate functions. Instead, the constant projection below returns zero rows for empty input and two rows for two input rows.
This differs from the SELECT reference manual's statement that, when no GROUP BY is present, all rows implicitly form a single aggregate group. Adding an aggregate function only in HAVING changes the result to one row. Replacing that HAVING condition with TRUE then changes the query's cardinality, even when both predicates are true.
This report concerns the discrepancy between documented semantics and observed behavior. Please determine whether implicit grouping is missing from the implementation or whether the documentation needs to explicitly describe MySQL's behavior for HAVING without aggregate functions. No particular internal root cause or regression version has been established.
## Actual versus documented behavior
| Query form | Input rows | Actual output rows | Expected under the documented single-group semantics |
| --- | --- | --- | --- |
| `SELECT 87 FROM having_input HAVING TRUE` | 0 | 0 | 1 row containing 87 |
| `SELECT 87 FROM having_input HAVING COUNT(k) < 84` | 0 | 1 | 1 row containing 87 |
| `SELECT 87 FROM having_input HAVING TRUE` | 2 | 2 | 1 row containing 87 |
| `SELECT 87 FROM having_input HAVING COUNT(k) < 84` | 2 | 1 | 1 row containing 87 |
The projection is a constant and HAVING TRUE is unconditionally true, so the example does not depend on which non-grouped input column value would be selected. The difference is the existence and number of output groups.
## Documentation discrepancy
The [MySQL 9.7 Reference Manual, Section 15.2.13, SELECT Statement](https://dev.mysql.com/doc/refman/9.7/en/select.html), in its explanation of HAVING, states:
> The HAVING clause specifies conditions on groups, typically formed by the GROUP BY clause. The query result includes only groups satisfying the HAVING conditions. (If no GROUP BY is present, all rows implicitly form a single aggregate group.)
The parenthetical statement does not state that an aggregate function must also appear in the query. Applied to A and C, it describes one implicit group, rather than zero or two output rows.
The same section documents MySQL extensions allowing HAVING to reference SELECT-list columns and outer-subquery columns. That explanation does not explicitly say that HAVING without aggregate functions is instead evaluated without implicit grouping. The reproduction uses only a constant projection and a constant HAVING condition.
The [MySQL 9.7 Reference Manual, Section 14.19.1, Aggregate Function Descriptions](https://dev.mysql.com/doc/refman/9.7/en/aggregate-functions.html) states:
> If you use an aggregate function in a statement containing no GROUP BY clause, it is equivalent to grouping on all rows.
That statement explains B and D, but does not specify an exception to the SELECT section's broader description of HAVING.
The [MySQL Handling of GROUP BY section](https://dev.mysql.com/doc/refman/9.7/en/group-by-handling.html) also discusses queries with aggregate functions and no GROUP BY. It does not, by itself, clarify whether the SELECT section's implicit-group statement is intended to exclude queries containing only HAVING TRUE.
These passages were checked in the MySQL 9.7 manual. Oracle's [official hosted copy of the SELECT section](https://docs.oracle.com/cd/E17952_01/mysql-9.7-en/select.html) contains the same single-aggregate-group statement.
## Expected behavior or requested documentation correction
If the SELECT documentation describes the intended semantics, A and C should each return exactly one row containing 87. Adding or removing an otherwise redundant aggregate reference in HAVING should not be necessary to obtain the documented implicit group.
If the observed behavior is intentional, please amend the HAVING documentation to state when implicit grouping occurs and explain that a HAVING clause without GROUP BY and without aggregate functions can preserve input-row cardinality, including returning zero rows for empty input.
How to repeat:
CREATE TABLE having_input (k INT);
-- A: HAVING without GROUP BY or aggregate functions, empty input.
SELECT 87 AS x FROM having_input HAVING TRUE;
-- Actual: zero rows.
-- B: an aggregate function appears only in HAVING, empty input.
SELECT 87 AS x FROM having_input HAVING COUNT(k) < 84;
-- Actual: one row containing 87.
INSERT INTO having_input VALUES (1), (2);
-- C: same query as A, now with two input rows.
SELECT 87 AS x FROM having_input HAVING TRUE;
-- Actual: two rows, both containing 87.
-- D: same query as B, now with two input rows.
SELECT 87 AS x FROM having_input HAVING COUNT(k) < 84;
-- Actual: one row containing 87.
-- E: retaining an aggregate reference with a true condition preserves one group.
SELECT 87 AS x FROM having_input HAVING COUNT(k) >= 0;
-- Actual: one row containing 87.
Portions of this website are copyright © 2001, 2002 The PHP Group
Page generated in 0.048 sec. using MySQL 8.4.7-u6-cloud
Timestamp references displayed by the system are UTC.
Content reproduced on this site is the property of the
respective copyright holders.
It is not reviewed in advance
by Oracle and does not necessarily represent the opinion of
Oracle or any other party.