Numeric Functions
Numeric functions round prices, find absolute differences, and calculate powers and roots. This lesson also explains why decimal calculations sometimes produce results like 2398.7999999999997 — and how to store money so they don't.
Rounding
SELECT round(19.987, 2) AS two_places, round(19.5) AS nearest_whole, ceil(19.01) AS rounded_up, floor(19.99) AS rounded_down;
| two_places | nearest_whole | rounded_up | rounded_down |
|---|---|---|---|
| 19.99 | 20 | 20 | 19 |
round(x, n) rounds to n decimal places (default 0). ceil (or ceiling) always goes up and floor always goes down. Rounding of exact halves (2.5) differs between databases and data types, so don't rely on it for financial rules — make the rule explicit.
Floating-point surprises
SELECT 0.1 + 0.2 AS looks_wrong, 19.99 * 120 AS also_odd;
| looks_wrong | also_odd |
|---|---|
| 0.30000000000000004 | 2398.7999999999997 |
Values like 0.1 can't be stored exactly in binary floating point (REAL, FLOAT, DOUBLE), so tiny errors appear. SQLite stores all decimals this way. Other databases have exact DECIMAL/NUMERIC types, where 0.1 + 0.2 is exactly 0.3.
SELECT round(0.1 + 0.2, 2) AS tidy, round(19.99 * 120, 2) AS also_tidy;
| tidy | also_tidy |
|---|---|
| 0.3 | 2398.8 |
DECIMAL(10, 2) in databases that support it exactly, or store whole cents in an INTEGER column (1999 for €19.99). Never use FLOAT for money.Absolute value and sign
SELECT first_name, salary, salary - 65000 AS difference, abs(salary - 65000) AS distance_from_65k, sign(salary - 65000) AS direction FROM employees WHERE department_id = 1;
| first_name | salary | difference | distance_from_65k | direction |
|---|---|---|---|---|
| Rafael | 82000 | 17000 | 17000 | 1 |
| Lucas | 52000 | -13000 | 13000 | -1 |
| Sofia | 54000 | -11000 | 11000 | -1 |
Powers, roots and other maths
SELECT power(2, 10) AS two_to_ten, sqrt(144) AS root, pi() AS pi, log10(1000) AS log_ten;
| two_to_ten | root | pi | log_ten |
|---|---|---|---|
| 1024 | 12 | 3.141592653589793 | 3 |
Most databases have a full maths library: power, sqrt, exp, ln, log, trigonometric functions and more. (SQLite includes them only when compiled with its maths extension; the build used here includes the common ones.)
Remainders
SELECT id, id % 3 AS group_number FROM orders WHERE id <= 6;
| id | group_number |
|---|---|
| 1 | 1 |
| 2 | 2 |
| 3 | 0 |
| 4 | 1 |
| 5 | 2 |
| 6 | 0 |
% gives the remainder after division — handy for splitting rows into buckets or finding even numbers (id % 2 = 0). The standard function form is MOD(a, b) (PostgreSQL, MySQL, Oracle).
Random numbers
SELECT name FROM products ORDER BY random() LIMIT 3;
Ordering by a random value picks random rows — fine for small tables, slow for big ones. The function is random() in SQLite and PostgreSQL, RAND() in MySQL and NEWID() for ordering in SQL Server. Run it in the editor below a few times to see different results.
Formatting numbers
SELECT name, format('€%.2f', price) AS price_label FROM products WHERE category = 'Toys';
| name | price_label |
|---|---|
| Jigsaw Puzzle 1000 | €18.00 |
| Wooden Train Set | €39.90 |
Formatting for display — currency symbols, thousands separators — is usually better done in the application, which knows the user's locale. When you need it in SQL, use format/printf (SQLite), to_char (PostgreSQL, Oracle), FORMAT (MySQL, SQL Server).
Try it yourself
Calculate each product's price including 23% VAT, rounded to two decimals, and pick three random products.