Is there a way to specify if we want to round a field value 4.485 to 4.48(half down) or to 4.49 (half up) in a sql query with MySql?
Thanks
Is there a way to specify if we want to round a field value 4.485 to 4.48(half down) or to 4.49 (half up) in a sql query with MySql?
Thanks
Even if the question is years old, I had the same problem and found a different solution I'd like to share.
Here it is: using a conditional function you explicitly decide which way you want to round when the last decimal is 5. For instance, if you want to round half up with 2 decimals:
SELECT IF ((TRUNCATE(mynumber*1000,0) mod 5) = 0,CEIL(mynumber*100)/100,ROUND(mynumber,2)) as value FROM mytable
You can use FLOOR function instead of CEIL if you want to round half down; if you want a different number of decimals, say n, you change the multiplier inside the TRUNCATE call (10^n+1) and you pass it to the ROUND function.
SELECT IF ((TRUNCATE(mynumber*([10^*n+1*]),0) mod 5) = 0,[CEIL|FLOOR](mynumber*100)/100,ROUND(mynumber,[*n*])) as value FROM mytable
Based on the official MySQL documentation there is no way to specify a rounding strategy. By default, ROUND uses the “round half up” rule for exact-value numbers.
However, I needed a function that behaves like java.math.BigDecimal with java.math.RoundingMode.HALF_DOWN mode. So the only solution that I found was to create my own function.
DELIMITER //
DROP FUNCTION IF EXISTS roundHalfDown //
CREATE FUNCTION roundHalfDown (
    numberToRound DECIMAL(25,15),
    roundingPrecision TINYINT(2)
)
    RETURNS DECIMAL(25,15)
BEGIN
    DECLARE digitPosition TINYINT (2) UNSIGNED DEFAULT 0;
    DECLARE digitToRound TINYINT (2) DEFAULT -1;
    DECLARE roundedNumber DECIMAL(20,6) DEFAULT 0;
    SET digitPosition = INSTR(numberToRound, '.');
    IF (roundingPrecision < 0) THEN
        SET digitPosition = digitPosition + roundingPrecision;
    ELSE
        SET digitPosition = digitPosition + roundingPrecision + 1;
    END IF;
    IF (digitPosition > 0
        AND digitPosition <= CHAR_LENGTH(numberToRound)
    ) THEN
        
        SET digitToRound = CAST(
                SUBSTR(
                numberToRound, 
                digitPosition, 
                1
            ) AS UNSIGNED
        );
        SET digitPosition = digitPosition - 1;
    END IF;
    IF (digitToRound > -1) THEN
        IF (digitToRound > 5) THEN
            SET roundedNumber = ROUND(numberToRound, roundingPrecision);
        ELSEIF (digitToRound = 5 AND CAST(
                SUBSTR(
                REPLACE(numberToRound, '.', ''), 
                digitPosition + 1
            ) AS UNSIGNED) > 0) THEN
            SET roundedNumber = ROUND(numberToRound, roundingPrecision);
        ELSE
            SET roundedNumber = TRUNCATE(numberToRound, roundingPrecision);
        END IF;
    ELSEIF (roundingPrecision > 0) THEN
        SET roundedNumber = numberToRound;
    END IF;
    RETURN roundedNumber;
END //
DELIMITER ;
SELECT roundHalfDown(1.541, 2); #1.54
SELECT roundHalfDown(1.545, 2); #1.54
SELECT roundHalfDown(1.5451, 2); #1.55
SELECT roundHalfDown(1.54500001, 2); #1.55
SELECT roundHalfDown(1.54499999, 2); #1.54
SELECT roundHalfDown(-1.545, 2); #-1.54
SELECT roundHalfDown(-1.5451, 2); #-1.55
SELECT roundHalfDown(555, 0); #555
SELECT roundHalfDown(1000999, -1); #1001000
SELECT roundHalfDown(1000999, -2); #1001000
SELECT roundHalfDown(1000999, -3); #1001000
SELECT roundHalfDown(1000999, -4); #1000000
I used this answer from another Stack Overflow question, but I changed it a bit for my specific case.
Andrea Pegoretti's answer is almost correct, however it will apply when it's a 5 or a 0 instead of just a 5.
My fix (for round down):
SELECT IF (SUBSTR(TRUNCATE(CEIL(mynumber*1000),0),-1) = 5,FLOOR(mynumber*100)/100,ROUND(mynumber, 2))) AS value FROM mytable
The accepted answer of this post offers a good solution : MySQL - How can I always round up decimals?
i.e multiply by 10^n where n is the decimal place you want to round to then call ceil to round up or floor to round down and divide by 10^n.
You can use the CEIL (or CEILING) and the FLOOR functions to round up/round down.
For example:
CEIL(4.485 * 100) / 100 will return 4.49
FLOOR(4.485 * 100) / 100 will return 4.48
I have the same question and I try all kind of custom function to emulate the functionality of PHP with a round up and down, but after a while, I figured out that MySQL produces different results using float and doubles fields.
Here my test.
mysql> describe test_redondeo;
+----------------+--------------+------+-----+---------+-------+
| Field          | Type         | Null | Key | Default | Extra |
+----------------+--------------+------+-----+---------+-------+
| columna_double | double(15,3) | YES  |     | NULL    |       |
| columna_float  | float(9,3)   | YES  |     | NULL    |       |
| id             | int(11)      | NO   | PRI | NULL    |       |
+----------------+--------------+------+-----+---------+-------+
3 rows in set (0.01 sec)
In fields type double, round function truncate, but in float round up.
mysql> select columna_double, columna_float, round ( columna_double, 2) as round_double, round ( columna_float, 2) as round_float from test_redondeo;
+----------------+---------------+--------------+-------------+
| columna_double | columna_float | round_double | round_float |
+----------------+---------------+--------------+-------------+
|        902.025 |       902.025 |       902.02 |      902.03 |
+----------------+---------------+--------------+-------------+
1 row in set (0.00 sec)
If you made a custom function for round a number using round() in any way, please pay attention to type of field.
Hope this test helps you.
According to Mysql docs,
I had also a situation, where I was wondering why is Mysql rounding(1) 74,447 to 74,4. It was because it was in fact an endless long decimal, a approximate-value number, and not a exact-value number. The solution for me was, that I had to use ROUND() 3x like this: ROUND(ROUND(ROUND(value, 3), 2), 1). The first rounding makes sure that it's not a approximate-value number any more (where Mysql uses the “round to nearest even” rule), but a exact-value number, a decimal 3 number.