Skip to content

MDEV-40779: Wrong result for DISTINCT with HAVING, ROLLUP - #6069

Open
DaveGosselin-MariaDB wants to merge 1 commit into
11.4from
11.4-mdev-40779-distinct-having-wrong-result
Open

DaveGosselin-MariaDB wants to merge 1 commit into
11.4from
11.4-mdev-40779-distinct-having-wrong-result

Conversation

@DaveGosselin-MariaDB

Copy link
Copy Markdown
Member

A query with DISTINCT over GROUP BY now reads AVG, STD and VARIANCE values from the DISTINCT temp table, and its ROLLUP rows pass HAVING while keeping NULL from the columns that they roll-up.

The following scenario now returns correct results of -1.0000:

  CREATE TABLE t1 (a INT);
  INSERT INTO t1 VALUES (1),(2),(3);
  SELECT DISTINCT -AVG(a) FROM t1 GROUP BY a HAVING AVG(a) < 2;

Only the group with average 1 passes HAVING and goes into the DISTINCT temp table. Duplicate removal checks HAVING again on that row, after all three groups have been read. The row now stores its own average, and the second check reads 1 from it. Before, the check read 3, the average of the last group, and deleted the row.

This scenario now returns 2, 2 (reusing DDL from above):

  SELECT DISTINCT a, a+0 FROM t1 GROUP BY a WITH ROLLUP HAVING a=2;

The ROLLUP total row has a=NULL and fails HAVING. For this query, HAVING is on the JOIN_TAB of the grouping table while JOIN::having is NULL. rollup_write_data considers JOIN_TAB::having if available, otherwise it falls back to JOIN::having which was set during JOIN::prepare. Without HAVING, SELECT DISTINCT a+0 over the same groups returns 1, 2, 3 and NULL. The ROLLUP row stores NULL for a even though a is not in the select list, and a+0 is computed from that stored a.

Assisted-By: Claude Opus 5.5 noreply@anthropic.com

A query with DISTINCT over GROUP BY now reads AVG, STD and VARIANCE
values from the DISTINCT temp table, and its ROLLUP rows pass HAVING
while keeping NULL from the columns that they roll-up.

The following scenario now returns correct results of -1.0000:

  CREATE TABLE t1 (a INT);
  INSERT INTO t1 VALUES (1),(2),(3);
  SELECT DISTINCT -AVG(a) FROM t1 GROUP BY a HAVING AVG(a) < 2;

Only the group with average 1 passes HAVING and goes into the DISTINCT
temp table.  Duplicate removal checks HAVING again on that row, after
all three groups have been read.  The row now stores its own average,
and the second check reads 1 from it.  Before, the check read 3, the
average of the last group, and deleted the row.

This scenario now returns 2, 2:

  SELECT DISTINCT a, a+0 FROM t1 GROUP BY a WITH ROLLUP HAVING a=2;

The ROLLUP total row has a=NULL and fails HAVING.  For this query,
HAVING is on the JOIN_TAB of the grouping table while JOIN::having is
NULL.  rollup_write_data considers JOIN_TAB::having if available,
otherwise it falls back to JOIN::having which was set during
JOIN::prepare.  Without HAVING, SELECT DISTINCT a+0 over the same
groups returns 1, 2, 3 and NULL.  The ROLLUP row stores NULL for a
even though a is not in the select list, and a+0 is computed from that
stored a.

Assisted-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Development

Successfully merging this pull request may close these issues.

1 participant