Uploaded image for project: 'MariaDB Server'
  1. MariaDB Server
  2. MDEV-41469

Wrong result: HAVING with COUNT(DISTINCT) is evaluated incorrectly when the grouped query also has a join and a window function

    XMLWordPrintable

Details

    • 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

          Activity

            People

              Unassigned Unassigned
              bradh352 Brad House
              Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Git Integration

                  Error rendering 'com.xiplink.jira.git.jira_git_plugin:git-issue-webpanel'. Please contact your Jira administrators.