Details
-
Bug
-
Status: Closed (View Workflow)
-
Major
-
Resolution: Duplicate
-
11.4.13, 11.8.9, 12.1.2, 13.0.2
-
None
-
Not for Release Notes
Description
A grouped query that has a join, a window function in the select list, and a HAVING clause using COUNT(DISTINCT ...) returns the wrong groups. It drops groups the HAVING clause admits and keeps groups it refuses. No error or warning is raised.
Removing any one of the four (the join, the window function, the HAVING clause, or the COUNT(DISTINCT)) gives the correct result. Computing the window function in an outer query over the grouped query as a derived table also gives the correct result.
MySQL 8.4.11 and 9.7.2 return the correct result for every query below. So do PostgreSQL 16 and SQLite.
Reproduced on every release line tested, from the official Docker images:
10.5.29, 10.6.28, 10.11.19, 11.4.13, 11.8.9, 12.0.2, 12.1.2, 13.0.2.
How to repeat:
CREATE TABLE t (issue INT NOT NULL, comp INT NOT NULL, build INT NOT NULL, w INT NOT NULL); |
CREATE TABLE c (id INT PRIMARY KEY, fold VARCHAR(10) NOT NULL); |
INSERT INTO c VALUES (10, 'a'); |
INSERT INTO t VALUES (1, 10, 1, 0), (1, 10, 2, 0), (2, 10, 1, 0); |
|
|
-- Issue 1 is in two builds; issue 2 is in one.
|
|
|
-- 1. Expected: issue 2, total 1. Actual: no rows.
|
SELECT t.issue, COUNT(*) OVER () AS total |
FROM t JOIN c ON c.id = t.comp |
GROUP BY t.issue |
HAVING COUNT(DISTINCT t.build) < 2 AND SUM(t.w) < 1; |
|
|
-- 2. Expected: issue 2, total 1. Actual: issues 2 and 1, total 2.
|
SELECT t.issue, COUNT(*) OVER () AS total |
FROM t JOIN c ON c.id = t.comp |
GROUP BY t.issue |
HAVING COUNT(DISTINCT t.build) < 2; |
|
|
-- 3. Expected: issue 1, total 1. Actual: no rows.
|
SELECT t.issue, COUNT(*) OVER () AS total |
FROM t JOIN c ON c.id = t.comp |
GROUP BY t.issue |
HAVING COUNT(DISTINCT t.build) > 1; |
|
|
-- 4. Query 1 without the join. Actual: issue 2, total 1 (correct).
|
SELECT t.issue, COUNT(*) OVER () AS total |
FROM t |
GROUP BY t.issue |
HAVING COUNT(DISTINCT t.build) < 2 AND SUM(t.w) < 1; |
|
|
-- 5. Query 1 with the window moved to an outer query. Actual: issue 2, total 1 (correct).
|
SELECT g.issue, COUNT(*) OVER () AS total |
FROM (SELECT t.issue |
FROM t JOIN c ON c.id = t.comp |
GROUP BY t.issue |
HAVING COUNT(DISTINCT t.build) < 2 AND SUM(t.w) < 1) AS g; |
Results by server:
| Server | Q1 | Q2 | Q3 | Q4 | Q5 |
|---|---|---|---|---|---|
| MariaDB 10.5.29 to 13.0.2 | no rows | issues 2 and 1, total 2 | no rows | issue 2, total 1 | issue 2, total 1 |
| MySQL 8.4.11, 9.7.2 | issue 2, total 1 | issue 2, total 1 | issue 1, total 1 | issue 2, total 1 | issue 2, total 1 |
In Q2 and Q3 the group with two builds behaves as if its distinct count were 1: it passes "< 2" and fails "> 1". Q1 also loses the group with one build, so the fault is not only the value the distinct count takes.
Found in an application's findings list, where the page came back empty while a separate count of the same groups returned one.
Attachments
Issue Links
- duplicates
-
MDEV-40884 Materializing a grouped input changes the result of a window query with `HAVING SUM(DISTINCT ...)`
-
- Confirmed
-