0

This is a simplified version of what I'm trying to do. I am trying to rank users based on how many miles they walked overall.

This data is stored in the table called walks. Every time a user makes a walk, an entry is added.

create temporary table walks
(
    id       int unsigned auto_increment primary key,
    user_id  int unsigned             not null,
    miles_walked float unsigned default '0' not null,
    date date not null
);

To fill in the table:

insert into walks (user_id, miles_walked, date)
values
    (1, 10.1, '2022-12-20'),
    (2, 60.2, '2022-12-21'),
    (3, 30.3, '2022-12-22'),
    (1, 0.4, '2022-12-23'),
    (2, 10.5, '2022-12-24'),
    (3, 10.6, '2022-12-25'),
    (1, 40.7, '2022-12-26'),
    (2, 80.8, '2022-12-27'),
    (3, 30.9, '2022-12-28');
select * from walks;

The result of the above query

select user_id,
       SUM(miles_walked) as miles_walked_total,
       ROUND(SUM(miles_walked), 1) as miles_walked_total_rounded,
       row_number() over (order by SUM(miles_walked) desc)  as miles_rank
from walks
group by user_id
order by user_id

The result of the above query

As you can see, rounding is WRONG for users with id 2 and 3. What happened? Like I said, this is a simplified example. In my real case, not just rounding, but the ranking is wrong for the whole set when I use functions like ROUND and LENGTH:

ROW_NUMBER() OVER (ORDER BY (SUM(LENGTH(reports.comments)) + SUM(report_items.report_items_characters_number)) DESC) AS ranking
Shadow
  • 33,525
  • 10
  • 51
  • 64
sergei
  • 803
  • 7
  • 12
  • 1
    Don't use imprecise floating point, use a decimal type. Then you don't need to round – ysth Dec 23 '22 at 09:44
  • Unless I'm missing something this is a bug. What does select version() show? – ysth Dec 23 '22 at 09:48
  • @ysth This is a simplified version. In the real case, we actually track meters walked. Then we convert them to miles. – sergei Dec 23 '22 at 09:49
  • @ysth select version(); 8.0.22 – sergei Dec 23 '22 at 09:50
  • Tested in mysql version 5.1.1, Its working fine ! – SelVazi Dec 23 '22 at 09:55
  • I can't duplicate it in 8.0.30 https://dbfiddle.uk/y04TcMlp I suspect it's a bug that's been fixed. – ysth Dec 23 '22 at 09:56
  • @SouhailV I suspect you are looking at a client version, not your server version. MySQL before version 8 didn't even have row_number. Do `select version();` to see your server version – ysth Dec 23 '22 at 09:58
  • @ysth I guess I will upgrade MySQL and see if everything works in the real scenario. I didn't even start thinking that it could be a MySQL bug - I thought I was doing something wrong. – sergei Dec 23 '22 at 09:58
  • 1
    But definitely avoid float; there's almost never a good reason to use that. Then your problem goes away – ysth Dec 23 '22 at 09:59
  • 1
    @ysth yep, I used it just for this example. Thank you! – sergei Dec 23 '22 at 10:00
  • Oh, sorry, missed your comment about meters – ysth Dec 23 '22 at 10:08
  • 1
    @ysth It works!!! Thank you very much! Do you want to post an answer so that I can accept it? – sergei Dec 23 '22 at 10:15
  • @SouhailV Thank you too for checking it in your env! – sergei Dec 23 '22 at 10:18

1 Answers1

1

I can't duplicate it in 8.0.30: https://dbfiddle.uk/y04TcMlp

I suspect it's a bug that's been fixed. I recommend you upgrade.

ysth
  • 96,171
  • 6
  • 121
  • 214