Bug #19690 | ORDER BY eliminates rows from the result | ||
---|---|---|---|
Submitted: | 10 May 2006 16:13 | Modified: | 21 Feb 2007 3:17 |
Reporter: | Baron Schwartz (Basic Quality Contributor) | Email Updates: | |
Status: | Closed | Impact on me: | |
Category: | MySQL Server: Optimizer | Severity: | S2 (Serious) |
Version: | 4.1.19/4.1BK | OS: | Linux (Gentoo Linux) |
Assigned to: | Ramil Kalimullin | CPU Architecture: | Any |
[10 May 2006 16:13]
Baron Schwartz
[10 May 2006 16:15]
Baron Schwartz
Run this file to populate the database with a set of test data that will trigger the bug.
Attachment: setup.sql (text/x-sql), 6.20 KiB.
[10 May 2006 16:18]
Baron Schwartz
When I said "I will attach a detailed test case to this bug" I meant "setup script" not "test case." Sorry for any confusion.
[10 May 2006 16:25]
MySQL Verification Team
Thank you for the bug report. The server's version you are reporting is pretty older, could you please test with the most recent 4.1.XX version released? Thanks in advance.
[10 May 2006 18:35]
Baron Schwartz
I am upgrading now.
[10 May 2006 18:41]
MySQL Verification Team
Thank you for the feedback. Open this bug report when you verified it with the new server. Thanks in advance.
[10 May 2006 19:24]
Baron Schwartz
I get the same results on 4.1.19.
[10 May 2006 19:44]
MySQL Verification Team
Thank you for the feedback. I will test now your db and offended query. Sorry I didn't noticed you had provide the dump file.
[10 May 2006 19:59]
Baron Schwartz
Here is another behavior that seems related. Run the setup script, in version 5.0.19-log. You need version 5.x so you can do a CAST as DECIMAL(8,2), which is not supported in earlier versions. Now run the following statements to create a copy of the data with the amounts as FLOAT instead of DECIMAL: alter table split change amount amount float not null default 0; select t.id, sum(amount) as balance, cast(sum(amount) as decimal(8,2)) as balance2 from transaction as t inner join split as s on t.id = s.transaction group by t.id having sum(amount) <> 0 order by cast(sum(amount) as decimal(8,2)); +---------------------------------+-----------------------+----------+ | id | balance | balance2 | +---------------------------------+-----------------------+----------+ | 3c6cb1aa8df451e0d2a234bea919edd | -0.000392764806747437 | 0.00 | | 182fedf6bf740de209da658362307d6 | 2.05039978027344e-05 | 0.00 | | e8e1fcd15fc82ae2cdc057341efe4af | -3.0517578125e-05 | 0.00 | | de59667992e5045ff98e8f0b798bb06 | 3.814697265625e-06 | 0.00 | | d7976b8667435bdb6939d5354a38102 | -5.96046447753906e-05 | 0.00 | | 9c6ab1d5a822205fbba82d5e93613dd | 5.7220458984375e-06 | 0.00 | | 96779b5478b7b4cda07e639729ac4ff | -2.92975455522537e-05 | 0.00 | | 81487469bdbc9e862ddaf068086aabe | -0.00031280517578125 | 0.00 | | 40509d65d986eaad08b06ef59afce31 | -8.392333984375e-05 | 0.00 | | 1e6f698e737158fcfb04eed030ca038 | 26.6499996185303 | 26.65 | | df6705732c57ce0979873bd566dd9ae | -0.00029754638671875 | 0.00 | | d8f6bf34a82b65005af11e53b69e9d0 | 6.866455078125e-05 | 0.00 | | a482d3416841b6870e22aeb7bc1e65b | 3.05473804473877e-07 | 0.00 | | 98c3a0a07af42bb0b96539e8ca6d31d | 7.62939453125e-05 | 0.00 | | 74bc51a3fba5c0961fa3aac5afb7dc3 | -0.000702857971191406 | 0.00 | +---------------------------------+-----------------------+----------+ The results are not ordered correctly. Again it looks like the ORDER BY may be done at the wrong time.
[10 May 2006 20:03]
Baron Schwartz
Here is another strange behavior. Run the setup script as before on version 4.1.19. Now remove the key on the 'split' table and run the query against just that table, instead of joining the 'split' and 'transaction' tables: alter table split drop key FK_split_transaction; select transaction, sum(amount) as balance from split group by transaction having sum(amount) <> 0; +---------------------------------+---------+ | transaction | balance | +---------------------------------+---------+ | 182fedf6bf740de209da658362307d6 | 0.00 | | 1e6f698e737158fcfb04eed030ca038 | 26.65 | | 3c6cb1aa8df451e0d2a234bea919edd | 0.00 | | 40509d65d986eaad08b06ef59afce31 | -0.00 | | 74bc51a3fba5c0961fa3aac5afb7dc3 | -0.00 | | 81487469bdbc9e862ddaf068086aabe | -0.00 | | 93e8e62b5da5b4366de03e6e62ade25 | 0.00 | | 96779b5478b7b4cda07e639729ac4ff | -0.00 | | 98c3a0a07af42bb0b96539e8ca6d31d | 0.00 | | 9c6ab1d5a822205fbba82d5e93613dd | -0.00 | | a482d3416841b6870e22aeb7bc1e65b | -0.00 | | d7976b8667435bdb6939d5354a38102 | 0.00 | | d8f6bf34a82b65005af11e53b69e9d0 | -0.00 | | de59667992e5045ff98e8f0b798bb06 | 0.00 | | df6705732c57ce0979873bd566dd9ae | 0.00 | | e8e1fcd15fc82ae2cdc057341efe4af | 0.00 | +---------------------------------+---------+ select transaction, sum(amount) as balance from split group by transaction having sum(amount) <> 0 order by balance; +---------------------------------+---------+ | transaction | balance | +---------------------------------+---------+ | 74bc51a3fba5c0961fa3aac5afb7dc3 | -0.00 | | 81487469bdbc9e862ddaf068086aabe | -0.00 | | d8f6bf34a82b65005af11e53b69e9d0 | -0.00 | | 40509d65d986eaad08b06ef59afce31 | -0.00 | | a482d3416841b6870e22aeb7bc1e65b | -0.00 | | 96779b5478b7b4cda07e639729ac4ff | -0.00 | | 9c6ab1d5a822205fbba82d5e93613dd | -0.00 | | de59667992e5045ff98e8f0b798bb06 | 0.00 | | 182fedf6bf740de209da658362307d6 | 0.00 | | e8e1fcd15fc82ae2cdc057341efe4af | 0.00 | | 98c3a0a07af42bb0b96539e8ca6d31d | 0.00 | | 93e8e62b5da5b4366de03e6e62ade25 | 0.00 | | d7976b8667435bdb6939d5354a38102 | 0.00 | | 3c6cb1aa8df451e0d2a234bea919edd | 0.00 | | df6705732c57ce0979873bd566dd9ae | 0.00 | | 1e6f698e737158fcfb04eed030ca038 | 26.65 | +---------------------------------+---------+ The ORDER BY clause no longer changes the results without that key.
[1 Jun 2006 0:54]
MySQL Verification Team
Thank you for the bug report. Notice that the wrong result is when the server returns 16 rows. You can see below that 5.0 server behaves correctly with both queries returning 1 row: miguel@hegel:~/dbs/4.1> bin/mysql -uroot Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 1 to server version: 4.1.21-debug Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> use test Database changed mysql> source /home/miguel/a/setup.sql Query OK, 0 rows affected (0.01 sec) <CUT> mysql> select t.id, sum(amount) as balance from transaction as t inner join -> split as s on t.id = s.transaction group by t.id having sum(amount) <> 0; +---------------------------------+---------+ | id | balance | +---------------------------------+---------+ | 182fedf6bf740de209da658362307d6 | 0.00 | | 1e6f698e737158fcfb04eed030ca038 | 26.65 | | 3c6cb1aa8df451e0d2a234bea919edd | 0.00 | | 40509d65d986eaad08b06ef59afce31 | -0.00 | | 74bc51a3fba5c0961fa3aac5afb7dc3 | -0.00 | | 81487469bdbc9e862ddaf068086aabe | -0.00 | | 93e8e62b5da5b4366de03e6e62ade25 | 0.00 | | 96779b5478b7b4cda07e639729ac4ff | -0.00 | | 98c3a0a07af42bb0b96539e8ca6d31d | 0.00 | | 9c6ab1d5a822205fbba82d5e93613dd | -0.00 | | a482d3416841b6870e22aeb7bc1e65b | -0.00 | | d7976b8667435bdb6939d5354a38102 | 0.00 | | d8f6bf34a82b65005af11e53b69e9d0 | -0.00 | | de59667992e5045ff98e8f0b798bb06 | 0.00 | | df6705732c57ce0979873bd566dd9ae | 0.00 | | e8e1fcd15fc82ae2cdc057341efe4af | 0.00 | +---------------------------------+---------+ 16 rows in set (0.01 sec) mysql> select t.id, sum(amount) as balance from transaction as t inner join -> split as s on t.id = s.transaction group by t.id having sum(amount) <> 0 order -> by balance; +---------------------------------+---------+ | id | balance | +---------------------------------+---------+ | 1e6f698e737158fcfb04eed030ca038 | 26.65 | +---------------------------------+---------+ 1 row in set (0.01 sec) -------------------------------------------------------------------------------------- mysql> select version(); +--------------+ | version() | +--------------+ | 4.1.21-debug | +--------------+ 1 row in set (0.00 sec) mysql> alter table transaction engine=MyISAM; Query OK, 16 rows affected (0.02 sec) Records: 16 Duplicates: 0 Warnings: 0 mysql> alter table split engine=MyISAM; Query OK, 84 rows affected (0.02 sec) Records: 84 Duplicates: 0 Warnings: 0 mysql> select t.id, sum(amount) as balance from transaction as t inner join -> split as s on t.id = s.transaction group by t.id having sum(amount) <> 0; +---------------------------------+---------+ | id | balance | +---------------------------------+---------+ | 182fedf6bf740de209da658362307d6 | 0.00 | | 1e6f698e737158fcfb04eed030ca038 | 26.65 | | 3c6cb1aa8df451e0d2a234bea919edd | 0.00 | | 40509d65d986eaad08b06ef59afce31 | -0.00 | | 74bc51a3fba5c0961fa3aac5afb7dc3 | -0.00 | | 81487469bdbc9e862ddaf068086aabe | -0.00 | | 93e8e62b5da5b4366de03e6e62ade25 | 0.00 | | 96779b5478b7b4cda07e639729ac4ff | -0.00 | | 98c3a0a07af42bb0b96539e8ca6d31d | 0.00 | | 9c6ab1d5a822205fbba82d5e93613dd | -0.00 | | a482d3416841b6870e22aeb7bc1e65b | -0.00 | | d7976b8667435bdb6939d5354a38102 | 0.00 | | d8f6bf34a82b65005af11e53b69e9d0 | -0.00 | | de59667992e5045ff98e8f0b798bb06 | 0.00 | | df6705732c57ce0979873bd566dd9ae | 0.00 | | e8e1fcd15fc82ae2cdc057341efe4af | 0.00 | +---------------------------------+---------+ 16 rows in set (0.01 sec) mysql> select t.id, sum(amount) as balance from transaction as t inner join -> split as s on t.id = s.transaction group by t.id having sum(amount) <> 0; +---------------------------------+---------+ | id | balance | +---------------------------------+---------+ | 182fedf6bf740de209da658362307d6 | 0.00 | | 1e6f698e737158fcfb04eed030ca038 | 26.65 | | 3c6cb1aa8df451e0d2a234bea919edd | 0.00 | | 40509d65d986eaad08b06ef59afce31 | -0.00 | | 74bc51a3fba5c0961fa3aac5afb7dc3 | -0.00 | | 81487469bdbc9e862ddaf068086aabe | -0.00 | | 93e8e62b5da5b4366de03e6e62ade25 | 0.00 | | 96779b5478b7b4cda07e639729ac4ff | -0.00 | | 98c3a0a07af42bb0b96539e8ca6d31d | 0.00 | | 9c6ab1d5a822205fbba82d5e93613dd | -0.00 | | a482d3416841b6870e22aeb7bc1e65b | -0.00 | | d7976b8667435bdb6939d5354a38102 | 0.00 | | d8f6bf34a82b65005af11e53b69e9d0 | -0.00 | | de59667992e5045ff98e8f0b798bb06 | 0.00 | | df6705732c57ce0979873bd566dd9ae | 0.00 | | e8e1fcd15fc82ae2cdc057341efe4af | 0.00 | +---------------------------------+---------+ 16 rows in set (0.00 sec) mysql> mysql> -------------------------------------------------------------------------------------- miguel@hegel:~/dbs/5.0> bin/mysql -uroot test Reading table information for completion of table and column names You can turn off this feature to get a quicker startup with -A Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 6 to server version: 5.0.23-debug Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> select t.id, sum(amount) as balance from transaction as t inner join -> split as s on t.id = s.transaction group by t.id having sum(amount) <> 0; +---------------------------------+---------+ | id | balance | +---------------------------------+---------+ | 1e6f698e737158fcfb04eed030ca038 | 26.65 | +---------------------------------+---------+ 1 row in set (0.01 sec) mysql> select t.id, sum(amount) as balance from transaction as t inner join -> split as s on t.id = s.transaction group by t.id having sum(amount) <> 0 order -> by balance; +---------------------------------+---------+ | id | balance | +---------------------------------+---------+ | 1e6f698e737158fcfb04eed030ca038 | 26.65 | +---------------------------------+---------+ 1 row in set (0.01 sec) mysql>
[31 Jan 2007 5:51]
Bugs System
A patch for this bug has been committed. After review, it may be pushed to the relevant source trees for release in the next version. You can access the patch from: http://lists.mysql.com/commits/19061 ChangeSet@1.2608, 2007-01-31 09:51:05+04:00, ramil@mysql.com +10 -0 fix for bug #19690: ORDER BY eliminates rows from the result Depending on the queries we use different data processing methods and can lose some data in case of double (and decimal in 4.1) fields. The fix consists of two parts: 1. double comparison changed, now double a is equal to double b if (a-b) is less than 5*0.1^(1 + max(a->decimals, b->decimals)). For example, if a->decimals==1, b->decimals==2, a==b if (a-b)<0.005 2. if we use a temporary table, store double values there as is to avoid any data conversion (rounding).
[14 Feb 2007 14:58]
Chad MILLER
Available in 4.1.23, 5.0.36, and 5.1.16-beta.
[21 Feb 2007 3:17]
Paul DuBois
Noted in 4.1.23, 5.0.36, 5.1.16 changelogs. ORDER BY on DOUBLE values could change the set of rows returned by a query. In 4.1, this also applies to DECIMAL.