Himanshu SharmaSoftware engineer
Let’s talk

MySQL · Lesson 17 of 50

Numeric functions

Round, truncate, compare and calculate with MySQL numeric functions and operators, and avoid floating point and integer division surprises.

12 minFunctionsUpdated 22 October 2026

Awaiting technical review. This lesson is readable but not yet listed in search engines.

By the end of this lessonUse arithmetic operators and numeric functions such as ROUND, CEIL, FLOOR, MOD and GREATEST, and understand DECIMAL versus floating point.

Arithmetic

MySQL can calculate with columns and constants. The basic operators are +, -, *, /, % (remainder, also written MOD) and DIV (integer division):

sql
SELECT 7 + 2 AS plus, 7 - 2 AS minus, 7 * 2 AS times, 7 / 2 AS divide, 7 DIV 2 AS whole, 7 % 2 AS remainder;
result
+------+-------+-------+--------+-------+-----------+
| plus | minus | times | divide | whole | remainder |
+------+-------+-------+--------+-------+-----------+
|    9 |     5 |    14 | 3.5000 |     3 |         1 |
+------+-------+-------+--------+-------+-----------+

Dividing by zero does not crash a query. It returns NULL (with a warning, and an error in strict mode inside INSERT or UPDATE):

sql
SELECT 5 / 0 AS result;
result
+--------+
| result |
+--------+
|   NULL |
+--------+

Rounding

Four functions cover almost all rounding needs:

Function Meaning x = 2.567
ROUND(x) nearest whole number 3
ROUND(x, 2) two decimal places 2.57
CEIL(x) up to a whole number 3
FLOOR(x) down to a whole number 2
TRUNCATE(x, 1) cut off, no rounding 2.5
sql
SELECT ROUND(2.567) AS r0, ROUND(2.567, 2) AS r2, CEIL(2.1) AS ceil_up, FLOOR(2.9) AS floor_down, TRUNCATE(2.567, 1) AS cut;
result
+----+------+---------+------------+-----+
| r0 | r2   | ceil_up | floor_down | cut |
+----+------+---------+------------+-----+
|  3 | 2.57 |       3 |          2 | 2.5 |
+----+------+---------+------------+-----+

Negative digits round to the left of the decimal point: ROUND(1234, -2) returns 1200.

Use them on real columns, for example to show prices with tax rounded to two places:

sql
SELECT name, price, ROUND(price * 1.18, 2) AS price_with_gst FROM products WHERE category_id = 2;
result
+-----------------------------+-------+----------------+
| name                        | price | price_with_gst |
+-----------------------------+-------+----------------+
| SQL Basics Handbook         | 29.95 |          35.34 |
| Web Design Patterns         | 34.50 |          40.71 |
| Data Structures Illustrated | 45.00 |          53.10 |
+-----------------------------+-------+----------------+

Other everyday functions

sql
SELECT ABS(-15) AS absolute, POW(2, 10) AS power, SQRT(81) AS root, SIGN(-4) AS sign, MOD(17, 5) AS remainder;
result
+----------+-------+------+------+-----------+
| absolute | power | root | sign | remainder |
+----------+-------+------+------+-----------+
|       15 |  1024 |    9 |   -1 |         2 |
+----------+-------+------+------+-----------+

GREATEST and LEAST pick the largest or smallest of several values in one row, which is different from MAX and MIN, which scan many rows:

sql
SELECT GREATEST(3, 9, 5) AS biggest, LEAST(3, 9, 5) AS smallest;
result
+---------+----------+
| biggest | smallest |
+---------+----------+
|       9 |        3 |
+---------+----------+

A useful pattern is clamping a value so it never goes below zero: GREATEST(stock - 10, 0).

Random numbers

RAND() returns a number between 0 and 1 that changes every call. It is useful for random samples:

sql
SELECT name FROM products ORDER BY RAND() LIMIT 3;

That picks three random products. Note that ORDER BY RAND() sorts the whole table, so avoid it on large tables.

Exact versus approximate numbers

This is a topic that causes real bugs. MySQL has two families of non-integer types:

  • DECIMAL(p, s) stores exact decimal numbers. p is the total digits and s the digits after the point.
  • FLOAT and DOUBLE store approximate binary fractions.

Many decimal fractions, like 0.1, cannot be represented exactly in binary. Compare:

sql
SELECT 0.1 + 0.2 AS decimal_math, 0.1e0 + 0.2e0 AS float_math, (0.1e0 + 0.2e0) = 0.3 AS float_equals;
result
+--------------+---------------------+--------------+
| decimal_math | float_math          | float_equals |
+--------------+---------------------+--------------+
|          0.3 | 0.30000000000000004 |            0 |
+--------------+---------------------+--------------+

The first value is exact. The second, written in scientific notation so that it is a DOUBLE, shows the tiny error, and comparing it for equality gives false. That is why you store prices in DECIMAL, as the sample products.price column does, and never in FLOAT. The data types lesson comes back to this.

Choosing rounding that matches the business rule

Rounding is not only a technical detail. Invoices, tax and discounts usually follow a rule written by an accountant or by law, such as "round each line to two decimals, then add" or "add everything, then round once". The two approaches can differ by a few paise. Decide the rule first, apply it in one place (a view or a function), and use the same one in every report. ROUND on a DECIMAL rounds halves away from zero, while on a DOUBLE the result depends on the binary value, another reason to keep money in DECIMAL.

Integer overflow

Integer columns have limits. A TINYINT holds -128 to 127 and an INT about plus or minus 2.1 billion. Arithmetic that exceeds the range raises an "out of range" error. Choose the type that fits the data. For ids that may grow large, use BIGINT.

Common mistakes

  • Expecting / to return a whole number.
  • Storing money in FLOAT.
  • Rounding too early. Round at the end of a calculation, not in the middle, or the errors add up.
  • Comparing floating point numbers with =.
  • Assuming RAND() is cheap on big tables.

Exercise

For each product in category 4 (Sports), show its name, the price rounded up to the next whole currency unit, and the number of whole boxes of 12 that the current stock could fill (use integer division).

Show one possible answer
sql
SELECT name, CEIL(price) AS price_rounded_up, stock DIV 12 AS full_boxes
FROM products
WHERE category_id = 4;
result
+------------------+------------------+------------+
| name             | price_rounded_up | full_boxes |
+------------------+------------------+------------+
| Yoga Mat         |               28 |          9 |
| Resistance Bands |               15 |         25 |
| Water Bottle     |               12 |         20 |
+------------------+------------------+------------+

Key points

  • Operators are +, -, *, / and % (or MOD). The / operator returns a decimal; DIV returns a whole number.
  • ROUND, CEIL, FLOOR and TRUNCATE control decimals. ROUND(x, 2) keeps two decimal places.
  • Use DECIMAL for money. FLOAT and DOUBLE are approximate and can give results like 0.30000000000000004.
  • GREATEST and LEAST compare several values in one row; MAX and MIN compare across rows.

Check yourself

1. What does 7 DIV 2 return?
2. Which function rounds 4.2 up to the next whole number?
3. Which data type should store money?
4. What does ROUND(2.567, 1) return?