Bug #71244 | Wrong result computation using ALL() and GROUP BY | ||
---|---|---|---|
Submitted: | 30 Dec 2013 9:48 | Modified: | 4 Mar 2014 16:02 |
Reporter: | Ralf Adams | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: DML | Severity: | S2 (Serious) |
Version: | 5.6.15, 5.5.35, 5.1.72, 5.7.3 | OS: | Any |
Assigned to: | CPU Architecture: | Any | |
Tags: | ALL(), GRPOUP BY, regression |
[30 Dec 2013 9:48]
Ralf Adams
[30 Dec 2013 11:09]
MySQL Verification Team
Hello Ralf, Thank you for the bug report and test case. Verified as described. Thanks, Umesh
[30 Dec 2013 11:10]
MySQL Verification Team
// 5.6.15 affected mysql> SELECT id1, SUM(value) AS `valuesum` -> FROM -> ( -- creating a virtual table as data source -> SELECT 1 AS 'id2', 1 AS 'id1', 3 AS 'value' -> UNION -> SELECT 2 AS 'id2', 1 AS 'id1', 6 AS 'value' -> UNION -> SELECT 3 AS 'id2', 1 AS 'id1', 9 AS 'value' -> UNION -> SELECT 4 AS 'id2', 2 AS 'id1', 8 AS 'value' -> UNION -> SELECT 5 AS 'id2', 2 AS 'id1', 10 AS 'value' -> ) AS `values` -> GROUP BY id1 -> HAVING valuesum > ALL(SELECT 6); +-----+----------+ | id1 | valuesum | +-----+----------+ | 1 | 33 | | 2 | 28 | +-----+----------+ 2 rows in set (0.00 sec) mysql> SELECT 1 AS 'id2', 1 AS 'id1', 3 AS 'value' -> UNION -> SELECT 2 AS 'id2', 1 AS 'id1', 6 AS 'value' -> UNION -> SELECT 3 AS 'id2', 1 AS 'id1', 9 AS 'value' -> UNION -> SELECT 4 AS 'id2', 2 AS 'id1', 8 AS 'value' -> UNION -> SELECT 5 AS 'id2', 2 AS 'id1', 10 AS 'value'; +-----+-----+-------+ | id2 | id1 | value | +-----+-----+-------+ | 1 | 1 | 3 | | 2 | 1 | 6 | | 3 | 1 | 9 | | 4 | 2 | 8 | | 5 | 2 | 10 | +-----+-----+-------+ 5 rows in set (0.00 sec) mysql> select version(); +------------+ | version() | +------------+ | 5.6.15-log | +------------+ 1 row in set (0.00 sec)
[30 Dec 2013 11:11]
MySQL Verification Team
/// 5.1.72 -- affected mysql> SELECT id1, SUM(value) AS `valuesum` -> FROM -> ( -- creating a virtual table as data source -> SELECT 1 AS 'id2', 1 AS 'id1', 3 AS 'value' -> UNION -> SELECT 2 AS 'id2', 1 AS 'id1', 6 AS 'value' -> UNION -> SELECT 3 AS 'id2', 1 AS 'id1', 9 AS 'value' -> UNION -> SELECT 4 AS 'id2', 2 AS 'id1', 8 AS 'value' -> UNION -> SELECT 5 AS 'id2', 2 AS 'id1', 10 AS 'value' -> ) AS `values` -> GROUP BY id1 -> HAVING valuesum > ALL(SELECT 6); +-----+----------+ | id1 | valuesum | +-----+----------+ | 1 | 33 | | 2 | 28 | +-----+----------+ 2 rows in set (0.09 sec) mysql> select version(); +-------------------------------------------+ | version() | +-------------------------------------------+ | 5.1.72-enterprise-commercial-advanced-log | +-------------------------------------------+ 1 row in set (0.00 sec)
[30 Dec 2013 11:13]
MySQL Verification Team
// 5.5.35 -- affected mysql> SELECT id1, SUM(value) AS `valuesum` -> FROM -> ( -- creating a virtual table as data source -> SELECT 1 AS 'id2', 1 AS 'id1', 3 AS 'value' -> UNION -> SELECT 2 AS 'id2', 1 AS 'id1', 6 AS 'value' -> UNION -> SELECT 3 AS 'id2', 1 AS 'id1', 9 AS 'value' -> UNION -> SELECT 4 AS 'id2', 2 AS 'id1', 8 AS 'value' -> UNION -> SELECT 5 AS 'id2', 2 AS 'id1', 10 AS 'value' -> ) AS `values` -> GROUP BY id1 -> HAVING valuesum > ALL(SELECT 6); +-----+----------+ | id1 | valuesum | +-----+----------+ | 1 | 33 | | 2 | 28 | +-----+----------+ 2 rows in set (0.00 sec) mysql> select version(); +------------+ | version() | +------------+ | 5.5.35-log | +------------+ 1 row in set (0.00 sec)
[30 Dec 2013 11:14]
MySQL Verification Team
/// 5.1.63 - Not affected mysql> SELECT id1, SUM(value) AS `valuesum` -> FROM -> ( -- creating a virtual table as data source -> SELECT 1 AS 'id2', 1 AS 'id1', 3 AS 'value' -> UNION -> SELECT 2 AS 'id2', 1 AS 'id1', 6 AS 'value' -> UNION -> SELECT 3 AS 'id2', 1 AS 'id1', 9 AS 'value' -> UNION -> SELECT 4 AS 'id2', 2 AS 'id1', 8 AS 'value' -> UNION -> SELECT 5 AS 'id2', 2 AS 'id1', 10 AS 'value' -> ) AS `values` -> GROUP BY id1 -> HAVING valuesum > ALL(SELECT 6); +-----+----------+ | id1 | valuesum | +-----+----------+ | 1 | 18 | | 2 | 18 | +-----+----------+ 2 rows in set (0.00 sec) mysql> select version(); +-----------+ | version() | +-----------+ | 5.1.63 | +-----------+ 1 row in set (0.00 sec)
[30 Dec 2013 11:17]
MySQL Verification Team
### Posgre results for this issue postgres=# select version(); version ------------------------------------------------------------------------------------------------------------ PostgreSQL 9.1.9 on x86_64-unknown-linux-gnu, compiled by gcc (Ubuntu/Linaro 4.6.3-1ubuntu5) 4.6.3, 64-bit (1 row) postgres=# SELECT id1, SUM(value) AS "valuesum" FROM ( SELECT 1 AS id2, 1 AS id1, 3 AS value UNION SELECT 2 AS id2, 1 AS id1, 6 AS value UNION SELECT 3 AS id2, 1 AS id1, 9 AS value UNION SELECT 4 AS id2, 2 AS id1, 8 AS value UNION SELECT 5 AS id2, 2 AS id1, 10 AS value ) AS values GROUP BY id1 having SUM(value) > ALL(SELECT 6); id1 | valuesum -----+---------- 1 | 18 2 | 18 (2 rows) postgres=# SELECT id1, SUM(value) AS "valuesum" FROM ( SELECT 1 AS id2, 1 AS id1, 3 AS value UNION SELECT 2 AS id2, 1 AS id1, 6 AS value UNION SELECT 3 AS id2, 1 AS id1, 9 AS value UNION SELECT 4 AS id2, 2 AS id1, 8 AS value UNION SELECT 5 AS id2, 2 AS id1, 10 AS value ) AS values GROUP BY id1; id1 | valuesum -----+---------- 1 | 18 2 | 18 (2 rows)
[30 Dec 2013 13:00]
MySQL Verification Team
// 5.7.3 mysql> select version(); +------------------------------------------+ | version() | +------------------------------------------+ | 5.7.3-m13-enterprise-commercial-advanced | +------------------------------------------+ 1 row in set (0.00 sec) mysql> SELECT id1, SUM(value) AS `valuesum` -> FROM -> ( -- creating a virtual table as data source -> SELECT 1 AS 'id2', 1 AS 'id1', 3 AS 'value' -> UNION -> SELECT 2 AS 'id2', 1 AS 'id1', 6 AS 'value' -> UNION -> SELECT 3 AS 'id2', 1 AS 'id1', 9 AS 'value' -> UNION -> SELECT 4 AS 'id2', 2 AS 'id1', 8 AS 'value' -> UNION -> SELECT 5 AS 'id2', 2 AS 'id1', 10 AS 'value' -> ) AS `values` -> GROUP BY id1 -> HAVING valuesum > ALL(SELECT 6); +-----+----------+ | id1 | valuesum | +-----+----------+ | 1 | 33 | | 2 | 28 | +-----+----------+ 2 rows in set (0.00 sec) // If we remove HAVING clause then results expected one mysql> SELECT id1, SUM(value) AS `valuesum` -> FROM -> ( -- creating a virtual table as data source -> SELECT 1 AS 'id2', 1 AS 'id1', 3 AS 'value' -> UNION -> SELECT 2 AS 'id2', 1 AS 'id1', 6 AS 'value' -> UNION -> SELECT 3 AS 'id2', 1 AS 'id1', 9 AS 'value' -> UNION -> SELECT 4 AS 'id2', 2 AS 'id1', 8 AS 'value' -> UNION -> SELECT 5 AS 'id2', 2 AS 'id1', 10 AS 'value' -> ) AS `values` -> GROUP BY id1 -> ; +-----+----------+ | id1 | valuesum | +-----+----------+ | 1 | 18 | | 2 | 18 | +-----+----------+ 2 rows in set (0.00 sec)
[4 Mar 2014 16:02]
Paul DuBois
Noted in 5.6.17, 5.7.4 changelogs. Aggregating the results of a subquery in the FROM clause could produce incorrect results.
[29 Mar 2014 8:30]
Laurynas Biveinis
5.6$ bzr log -r 5849 -n0 ------------------------------------------------------------ revno: 5849 committer: Chaithra Gopalareddy <chaithra.gopalareddy@oracle.com> branch nick: mysql-5.6 timestamp: Fri 2014-02-28 15:01:41 +0530 message: Bug#18014565: WRONG RESULT COMPUTATION USING ALL() AND GROUP BY Problem: Aggregation does not happen correctly because substitution for subquery is created with wrong item. Analysis: Currently while creating a substitution for ALL/ANY subqueries, optimizer uses "real_item" instead of the ref_item. If this happens to be a reference to an aggregate function then it would be creating the substitution with SUM_FUNC_ITEM rather than the REF_ITEM. If an aggregate function is present in having clause, optimizer calls split_sum_func2 to add the aggregate functions to the list of items in the select list. Ex: In the following query select f1, sum(f2) as sum from t1 group by f1 having sum > all (select 1); "sum" in having clause is a reference to sum(f2). So while creating the substitution we create using the real_item of "sum" which is sum(f2). In split_sum_func2 we add this "sum(f2)" to the item list. As a result the item list now becomes "sum(f2), f1, sum(f2)". This results in creation of three fields in tmp_table. But both the sum(f2)'s would be pointing to the same result_field. So, while aggregating same result is added twice. Before the fix for Bug#16095534, the type would remain REF_ITEM and thereby optimizer would not be adding "sum" to the select item list. Solution: The problem addressed in Bug#16095534 exists only for Item_ref objects created while resolving not for the ref objects created during parsing. So use real_item only for such items.
[29 Mar 2014 8:31]
Laurynas Biveinis
5.6$ bzr log -r 5850 -n0 ------------------------------------------------------------ revno: 5850 tags: clone-5.6.17-build committer: Chaithra Gopalareddy <chaithra.gopalareddy@oracle.com> branch nick: mysql-5.6 timestamp: Mon 2014-03-03 15:58:21 +0530 message: Post push fix for Bug#18014565