Skip to main content

SQL Built-In Numeric Functions

Numbers drive business logic in every database. Prices need rounding for display, tax calculations require precise arithmetic, financial reports depend on correct totals, and analytics queries compute percentages, averages, and growth rates. Raw numeric data rarely arrives in the exact form you need, and the calculations you perform on it must be accurate.

SQL numeric functions let you round, truncate, compute absolute values, perform modular arithmetic, raise numbers to powers, and much more, all directly in your queries. Combined with basic arithmetic operators, they give you a complete mathematical toolkit that runs inside the database engine, close to the data, without pulling numbers into application code for processing.

This guide covers every essential numeric function with practical examples and outputs, explains arithmetic in SELECT statements, and highlights the pitfalls that trip up developers working with numbers in SQL.

The Sample Data

All examples use these tables:

CREATE TABLE products (
product_id INT PRIMARY KEY,
product_name VARCHAR(100),
category VARCHAR(50),
price DECIMAL(10,2),
cost DECIMAL(10,2),
stock_qty INT
);

CREATE TABLE orders (
order_id INT PRIMARY KEY,
customer_id INT,
order_date DATE,
subtotal DECIMAL(10,2),
tax_rate DECIMAL(5,4),
discount_pct DECIMAL(5,2)
);

INSERT INTO products VALUES
(101, 'Wireless Mouse', 'Electronics', 25.99, 12.50, 150),
(102, 'USB-C Cable', 'Electronics', 9.99, 3.75, 300),
(103, 'Notebook A5', 'Stationery', 4.50, 1.80, 500),
(104, 'Mechanical Keyboard', 'Electronics', 89.99, 42.00, 45),
(105, 'Desk Lamp', 'Furniture', 34.50, 18.25, 0),
(106, 'Pen Pack', 'Stationery', 2.99, 0.95, 800),
(107, 'Standing Desk', 'Furniture', 299.99, 155.00, 12);

INSERT INTO orders VALUES
(1001, 1, '2024-06-01', 155.97, 0.0875, 10.00),
(1002, 2, '2024-06-03', 299.99, 0.0625, 0.00),
(1003, 1, '2024-06-05', 45.48, 0.0875, 5.00),
(1004, 3, '2024-06-07', 89.99, 0.1000, 15.00),
(1005, 2, '2024-06-10', 9.99, 0.0625, 0.00);

Arithmetic in SELECT

Before diving into functions, let's cover the foundation: SQL supports standard arithmetic operators directly in SELECT statements, WHERE clauses, and anywhere an expression is valid.

The Operators

OperatorOperationExampleResult
+Addition10 + 313
-Subtraction10 - 37
*Multiplication10 * 330
/Division10 / 33 or 3.333... (depends on types)
%Modulo (remainder)10 % 31

Basic Arithmetic Examples

Calculate profit margin per product:

SELECT
product_name,
price,
cost,
price - cost AS profit,
(price - cost) / price * 100 AS margin_pct
FROM products;
product_namepricecostprofitmargin_pct
Wireless Mouse25.9912.5013.4951.90
USB-C Cable9.993.756.2462.46
Notebook A54.501.802.7060.00
Mechanical Keyboard89.9942.0047.9953.33
Desk Lamp34.5018.2516.2547.10
Pen Pack2.990.952.0468.23
Standing Desk299.99155.00144.9948.33

Calculate total inventory value:

SELECT
product_name,
price,
stock_qty,
price * stock_qty AS inventory_value
FROM products
ORDER BY inventory_value DESC;
product_namepricestock_qtyinventory_value
Wireless Mouse25.991503898.50
Standing Desk299.99123599.88
USB-C Cable9.993002997.00
Pen Pack2.998002392.00
Notebook A54.505002250.00
Mechanical Keyboard89.99454049.55
Desk Lamp34.5000.00

Calculate order totals with tax and discount:

SELECT
order_id,
subtotal,
discount_pct,
subtotal * (1 - discount_pct / 100) AS after_discount,
subtotal * (1 - discount_pct / 100) * (1 + tax_rate) AS final_total
FROM orders;
order_idsubtotaldiscount_pctafter_discountfinal_total
1001155.9710155.97169.61737499999998
1002299.990299.99318.739375
100345.48545.4849.45949999999999
100489.991589.9998.989
10059.9909.9910.614375

The results have too many decimal places. This is where rounding functions become essential.

Integer Division Trap

The most common arithmetic mistake in SQL involves division between integers:

-- Integer division: result is truncated to integer in some databases
SELECT 10 / 3 AS result;
Database10 / 3 Result
PostgreSQL3 (integer division)
MySQL3.3333 (returns decimal)
SQL Server3 (integer division)
Oracle3.3333... (returns decimal)
SQLite3 (integer division)
danger

In PostgreSQL, SQL Server, and SQLite, dividing two integers performs integer division, truncating the decimal portion entirely. 10 / 3 returns 3, not 3.333.

Wrong:

SELECT 7 / 2 AS result;
-- PostgreSQL/SQL Server/SQLite: 3 (not 3.5!)

Fix: Cast at least one operand to a decimal type:

SELECT 7.0 / 2 AS result;           -- 3.5
SELECT CAST(7 AS DECIMAL) / 2; -- 3.5
SELECT 7 / 2.0 AS result; -- 3.5
SELECT 7::DECIMAL / 2; -- 3.5 (PostgreSQL)

Division by Zero

Dividing by zero raises an error in most databases:

SELECT 100 / 0;
-- ERROR: division by zero

Protect against it:

-- Use NULLIF to turn 0 into NULL (division by NULL returns NULL, not error)
SELECT
product_name,
price / NULLIF(stock_qty, 0) AS price_per_unit_in_stock
FROM products;
product_nameprice_per_unit_in_stock
Wireless Mouse0.17
Desk LampNULL

The Desk Lamp has stock_qty = 0. Without NULLIF, this query would crash. With NULLIF(stock_qty, 0), zero becomes NULL, and price / NULL safely returns NULL.

tip

NULLIF(a, b) returns NULL if a = b, otherwise returns a. Wrapping the divisor in NULLIF(divisor, 0) is the standard pattern for safe division in SQL.

ROUND: Rounding Numbers

ROUND rounds a number to a specified number of decimal places.

Syntax

ROUND(number, decimal_places)
ROUND(number) -- rounds to nearest integer (0 decimal places)

Examples

SELECT
ROUND(3.14159, 2) AS two_places,
ROUND(3.14159, 0) AS zero_places,
ROUND(3.14159) AS no_arg,
ROUND(3.5) AS half_up,
ROUND(2.5) AS half_up2,
ROUND(-3.7) AS negative;
two_placeszero_placesno_arghalf_uphalf_up2negative
3.143343-4
warning

Banker's rounding: PostgreSQL and some other databases use "round half to even" (banker's rounding), where .5 rounds to the nearest even number. So ROUND(2.5) returns 2, not 3, and ROUND(3.5) returns 4.

MySQL and SQL Server use the traditional "round half up" rule where .5 always rounds up.

ExpressionPostgreSQLMySQLSQL Server
ROUND(2.5)233
ROUND(3.5)444
ROUND(4.5)455

This difference can cause discrepancies in financial calculations when migrating between databases.

Practical: round order totals to 2 decimal places:

SELECT
order_id,
subtotal,
discount_pct,
tax_rate,
ROUND(subtotal * (1 - discount_pct / 100) * (1 + tax_rate), 2) AS final_total
FROM orders;
order_idsubtotaldiscount_pcttax_ratefinal_total
1001155.97100.0875169.62
1002299.9900.0625318.74
100345.4850.087549.46
100489.99150.100098.99
10059.9900.062510.61

Clean, two-decimal results ready for display.

Rounding to Negative Decimal Places

You can round to the left of the decimal point by using negative values:

SELECT
ROUND(1234.56, -1) AS tens,
ROUND(1234.56, -2) AS hundreds,
ROUND(1234.56, -3) AS thousands;
tenshundredsthousands
123012001000

Useful for rounding prices to the nearest $10, $100, etc., or for creating histogram buckets.

TRUNC / TRUNCATE: Rounding Without Rounding

TRUNC (PostgreSQL, Oracle) or TRUNCATE (MySQL) removes decimal digits without rounding. It simply chops off the unwanted digits.

-- PostgreSQL / Oracle
SELECT TRUNC(3.789, 1) AS truncated;
-- Result: 3.7 (not 3.8)

-- MySQL
SELECT TRUNCATE(3.789, 1) AS truncated;
-- Result: 3.7

-- Comparison
SELECT
ROUND(3.789, 1) AS rounded, -- 3.8
TRUNC(3.789, 1) AS truncated; -- 3.7
info

SQL Server does not have a TRUNC or TRUNCATE function for numbers. Use ROUND with a third argument of 1 to truncate:

-- SQL Server: ROUND with truncation flag
SELECT ROUND(3.789, 1, 1) AS truncated;
-- Result: 3.7

CEIL and FLOOR: Rounding to Integers

CEIL (or CEILING) rounds up to the nearest integer. FLOOR rounds down to the nearest integer.

Syntax

CEIL(number)     -- PostgreSQL, MySQL, Oracle
CEILING(number) -- SQL Server (also supported by PostgreSQL and MySQL)
FLOOR(number)

Examples

SELECT
CEIL(3.2) AS ceil_positive,
CEIL(3.8) AS ceil_high,
CEIL(-3.2) AS ceil_negative,
FLOOR(3.8) AS floor_positive,
FLOOR(3.2) AS floor_low,
FLOOR(-3.2) AS floor_negative;
ceil_positiveceil_highceil_negativefloor_positivefloor_lowfloor_negative
44-333-4

Notice how they behave with negative numbers:

  • CEIL(-3.2) = -3 (rounds toward zero, which is "up" on the number line)
  • FLOOR(-3.2) = -4 (rounds away from zero, which is "down" on the number line)

Practical Use Cases

Calculate number of shipping boxes needed:

-- Each box holds 25 items. How many boxes per product?
SELECT
product_name,
stock_qty,
CEIL(stock_qty / 25.0) AS boxes_needed
FROM products
WHERE stock_qty > 0;
product_namestock_qtyboxes_needed
Wireless Mouse1506
USB-C Cable30012
Notebook A550020
Mechanical Keyboard452
Pen Pack80032
Standing Desk121

CEIL ensures partial boxes are rounded up. 45 items / 25 per box = 1.8, rounded up to 2 boxes.

Calculate pages needed for pagination:

-- 7 products, 3 per page
SELECT CEIL(COUNT(*) / 3.0) AS total_pages FROM products;
-- Result: 3 (pages 1-3, with the last page having only 1 item)

Price tiers using FLOOR:

-- Group products by $10 price tiers
SELECT
product_name,
price,
FLOOR(price / 10) * 10 AS price_tier
FROM products
ORDER BY price_tier;
product_namepriceprice_tier
Pen Pack2.990
Notebook A54.500
USB-C Cable9.990
Wireless Mouse25.9920
Desk Lamp34.5030
Mechanical Keyboard89.9980
Standing Desk299.99290

CEIL, FLOOR, ROUND Compared

SELECT
value,
FLOOR(value) AS floor_val,
CEIL(value) AS ceil_val,
ROUND(value) AS round_val
FROM (VALUES (2.3), (2.5), (2.7), (-2.3), (-2.5), (-2.7))
AS t(value);
valuefloor_valceil_valround_val
2.3232
2.5233*
2.7233
-2.3-3-2-2
-2.5-3-2-3*
-2.7-3-2-3

*Rounding behavior for .5 varies by database (see the ROUND section above).

ABS: Absolute Value

ABS returns the absolute (non-negative) value of a number, stripping any negative sign.

Syntax

ABS(number)

Examples

SELECT
ABS(42) AS positive,
ABS(-42) AS negative,
ABS(0) AS zero,
ABS(-3.14) AS decimal_neg;
positivenegativezerodecimal_neg
424203.14

Practical: find products with price closest to a target:

-- Products closest to $30
SELECT
product_name,
price,
ABS(price - 30) AS distance_from_30
FROM products
ORDER BY distance_from_30
LIMIT 3;
product_namepricedistance_from_30
Wireless Mouse25.994.01
Desk Lamp34.504.50
USB-C Cable9.9920.01

Calculate price variance from average:

SELECT
product_name,
price,
ROUND(price - AVG(price) OVER(), 2) AS diff_from_avg,
ROUND(ABS(price - AVG(price) OVER()), 2) AS abs_diff
FROM products;
product_namepricediff_from_avgabs_diff
Wireless Mouse25.99-40.8640.86
USB-C Cable9.99-56.8656.86
Notebook A54.50-62.3562.35
Mechanical Keyboard89.9923.1423.14
Desk Lamp34.50-32.3532.35
Pen Pack2.99-63.8663.86
Standing Desk299.99233.14233.14

MOD: Remainder (Modulo)

MOD returns the remainder after dividing one number by another.

Syntax

-- Function syntax (all databases)
MOD(dividend, divisor)

-- Operator syntax (PostgreSQL, MySQL, SQL Server, SQLite)
dividend % divisor

Examples

SELECT
MOD(10, 3) AS mod_10_3,
MOD(15, 5) AS mod_15_5,
MOD(7, 2) AS mod_7_2,
MOD(10, 4) AS mod_10_4;
mod_10_3mod_15_5mod_7_2mod_10_4
1012

Check if a number is even or odd:

SELECT
product_id,
product_name,
CASE WHEN MOD(product_id, 2) = 0 THEN 'Even' ELSE 'Odd' END AS parity
FROM products;
product_idproduct_nameparity
101Wireless MouseOdd
102USB-C CableEven
103Notebook A5Odd
104Mechanical KeyboardEven
105Desk LampOdd
106Pen PackEven
107Standing DeskOdd

Alternate row coloring for reports:

SELECT
product_name,
price,
CASE WHEN MOD(ROW_NUMBER() OVER (ORDER BY product_name), 2) = 0
THEN 'light' ELSE 'dark'
END AS row_color
FROM products;

Distribute items across groups:

-- Distribute products into 3 groups
SELECT
product_name,
MOD(product_id, 3) AS group_number
FROM products;
product_namegroup_number
Wireless Mouse2
USB-C Cable0
Notebook A51
Mechanical Keyboard2
Desk Lamp0
Pen Pack1
Standing Desk2

Check divisibility:

-- Find order IDs that are multiples of 2
SELECT order_id FROM orders WHERE MOD(order_id, 2) = 0;
-- Results: 1002, 1004

POWER and SQRT: Exponents and Roots

POWER raises a number to a specified exponent. SQRT returns the square root.

Syntax

POWER(base, exponent)
SQRT(number)

Examples

SELECT
POWER(2, 3) AS two_cubed,
POWER(10, 2) AS ten_squared,
POWER(5, 0) AS any_to_zero,
POWER(2, 10) AS two_to_ten,
SQRT(144) AS sqrt_144,
SQRT(2) AS sqrt_2;
two_cubedten_squaredany_to_zerotwo_to_tensqrt_144sqrt_2
810011024121.4142135623730951

Compound interest calculation:

-- Future value of $1000 at 5% annual interest over 10 years
SELECT
1000 AS principal,
0.05 AS rate,
10 AS years,
ROUND(1000 * POWER(1 + 0.05, 10), 2) AS future_value;
principalrateyearsfuture_value
10000.05101628.89

Geometric mean of prices:

-- Geometric mean using POWER and logarithms
SELECT
ROUND(POWER(
EXP(SUM(LN(price))),
1.0 / COUNT(*)
), 2) AS geometric_mean
FROM products;
geometric_mean
22.85

Calculate distance between two points (Pythagorean theorem):

-- Distance between (3, 4) and (7, 1)
SELECT ROUND(SQRT(POWER(7 - 3, 2) + POWER(1 - 4, 2)), 2) AS distance;
-- Result: 5.00

SIGN: Determining Positive, Negative, or Zero

SIGN returns -1, 0, or 1 depending on whether the number is negative, zero, or positive.

Syntax

SIGN(number)

Examples

SELECT
SIGN(42) AS positive,
SIGN(-42) AS negative,
SIGN(0) AS zero;
positivenegativezero
1-10

Classify profit/loss:

SELECT
product_name,
price - cost AS profit,
CASE SIGN(price - cost)
WHEN 1 THEN 'Profit'
WHEN 0 THEN 'Break Even'
WHEN -1 THEN 'Loss'
END AS classification
FROM products;
product_nameprofitclassification
Wireless Mouse13.49Profit
USB-C Cable6.24Profit
Notebook A52.70Profit
Mechanical Keyboard47.99Profit
Desk Lamp16.25Profit
Pen Pack2.04Profit
Standing Desk144.99Profit

LOG and EXP: Logarithmic Functions

These functions handle logarithmic and exponential calculations. They are used less frequently in everyday application queries but are essential for statistical analysis, financial modeling, and scientific computations.

Syntax

-- Natural logarithm (base e)
LN(number) -- PostgreSQL, Oracle, MySQL
LOG(number) -- SQL Server (natural log), MySQL (natural log)

-- Base-10 logarithm
LOG10(number) -- all databases
LOG(10, number) -- PostgreSQL, Oracle (general form)

-- Exponential (e raised to the power)
EXP(number) -- all databases

Examples

SELECT
LN(2.71828) AS ln_e,
LOG10(1000) AS log10_thousand,
EXP(1) AS e_to_1,
EXP(0) AS e_to_0;
ln_elog10_thousande_to_1e_to_0
0.99999932734728232.7182818284590451
info

LOG function inconsistency: The meaning of LOG() varies across databases.

DatabaseLOG(x)LN(x)LOG10(x)
PostgreSQLBase-10 logNatural logSame as LOG(x)
MySQLNatural logNatural logBase-10 log
SQL ServerNatural logNot availableBase-10 log
OracleBase-10 logNatural logNot available (use LOG(10, x))

To avoid confusion, use LN() for natural logarithm and LOG10() for base-10 logarithm when your database supports both.

Combining Numeric Functions: Practical Recipes

Full Order Calculation

Calculate discount, tax, and final total in one query:

SELECT
order_id,
subtotal,
discount_pct,
ROUND(subtotal * discount_pct / 100, 2) AS discount_amount,
ROUND(subtotal * (1 - discount_pct / 100), 2) AS after_discount,
ROUND(subtotal * (1 - discount_pct / 100) * tax_rate, 2) AS tax_amount,
ROUND(subtotal * (1 - discount_pct / 100) * (1 + tax_rate), 2) AS final_total
FROM orders;
order_idsubtotaldiscount_pctdiscount_amountafter_discounttax_amountfinal_total
1001155.9710.0015.60140.3712.28152.66
1002299.990.000.00299.9918.75318.74
100345.485.002.2743.213.7846.99
100489.9915.0013.5076.497.6584.14
10059.990.000.009.990.6210.61

Markup and Margin Analysis

SELECT
product_name,
cost,
price,
ROUND((price - cost) / cost * 100, 1) AS markup_pct,
ROUND((price - cost) / price * 100, 1) AS margin_pct,
ROUND(price / cost, 2) AS price_to_cost_ratio
FROM products
ORDER BY margin_pct DESC;
product_namecostpricemarkup_pctmargin_pctprice_to_cost_ratio
Pen Pack0.952.99214.768.23.15
USB-C Cable3.759.99166.462.52.66
Notebook A51.804.50150.060.02.50
Mechanical Keyboard42.0089.99114.353.32.14
Wireless Mouse12.5025.99107.951.92.08
Standing Desk155.00299.9993.548.31.94
Desk Lamp18.2534.5089.047.11.89

Percentage of Total

SELECT
product_name,
price * stock_qty AS inventory_value,
ROUND(
price * stock_qty / SUM(price * stock_qty) OVER() * 100,
1
) AS pct_of_total
FROM products
ORDER BY inventory_value DESC;
product_nameinventory_valuepct_of_total
Mechanical Keyboard4049.5521.1
Wireless Mouse3898.5020.3
Standing Desk3599.8818.8
USB-C Cable2997.0015.6
Pen Pack2392.0012.5
Notebook A52250.0011.7
Desk Lamp0.000.0

Safe Percentage Calculations

-- Calculate discount percentage safely (handles zero subtotal)
SELECT
order_id,
subtotal,
discount_pct,
ROUND(
COALESCE(
discount_pct / NULLIF(subtotal, 0) * subtotal,
0
), 2
) AS discount_amount
FROM orders;
order_idsubtotaldiscount_pctdiscount_amount
1001155.9710.0010.00
1002299.990.000.00
100345.485.005.00
100489.9915.0015.00
10059.990.000.00

Common Mistakes

Mistake 1: Integer Division Silently Truncating Results

-- PostgreSQL / SQL Server / SQLite
SELECT 1 / 3 AS result;
-- Result: 0 (not 0.333)

SELECT 5 / 2 AS result;
-- Result: 2 (not 2.5)

Fix: Make at least one operand a decimal:

SELECT 1.0 / 3 AS result;   -- 0.333...
SELECT 5 / 2.0 AS result; -- 2.5

Mistake 2: Not Handling Division by Zero

-- Crashes the entire query
SELECT price / stock_qty FROM products;
-- ERROR: division by zero (when stock_qty = 0)

Fix:

SELECT price / NULLIF(stock_qty, 0) FROM products;
-- Returns NULL instead of crashing

Mistake 3: Rounding at the Wrong Stage

Rounding intermediate results instead of the final result introduces cumulative errors:

Wrong:

-- Rounding at each step loses precision
SELECT
ROUND(subtotal * 0.10, 2) AS discount, -- rounded
ROUND(
(subtotal - ROUND(subtotal * 0.10, 2)) * 0.0875,
2
) AS tax -- based on rounded discount
FROM orders WHERE order_id = 1001;

Correct:

-- Calculate with full precision, round only at the end
SELECT
ROUND(subtotal * (1 - discount_pct / 100) * (1 + tax_rate), 2) AS final_total
FROM orders WHERE order_id = 1001;
warning

Golden rule for financial calculations: Perform all arithmetic with full precision and round only the final result. Rounding intermediate values creates "penny errors" that compound across thousands of transactions.

Mistake 4: Using FLOAT for Money

-- FLOAT arithmetic is imprecise
SELECT CAST(0.1 AS FLOAT) + CAST(0.2 AS FLOAT);
-- May return: 0.30000000000000004 instead of 0.3

-- DECIMAL arithmetic is exact
SELECT CAST(0.1 AS DECIMAL(10,2)) + CAST(0.2 AS DECIMAL(10,2));
-- Returns exactly: 0.30

Always use DECIMAL or NUMERIC for monetary values.

Mistake 5: Forgetting Operator Precedence

SQL follows standard mathematical precedence: multiplication and division before addition and subtraction.

-- Not what you might expect
SELECT 100 + 50 * 0.10;
-- Result: 105.0 (not 15.0)
-- Evaluates as: 100 + (50 * 0.10) = 100 + 5 = 105

-- Use parentheses for clarity
SELECT (100 + 50) * 0.10;
-- Result: 15.0
tip

Always use parentheses in complex expressions, even when operator precedence would give the correct result. Parentheses make your intent explicit and prevent bugs from misreading the expression.

-- Unclear: does the discount apply before or after tax?
SELECT subtotal - discount_pct / 100 * subtotal + tax_amount

-- Clear: discount applied first, then tax added
SELECT (subtotal * (1 - discount_pct / 100)) + tax_amount

Database Compatibility Reference

FunctionPostgreSQLMySQLSQL ServerOracleSQLite
ROUND(n, d)YesYesYesYesYes
CEIL() / CEILING()BothBothCEILING()CEIL()No*
FLOOR()YesYesYesYesNo*
ABS()YesYesYesYesYes
MOD(a, b)YesYesUse %YesUse %
% operatorYesYesYesNoYes
POWER(b, e)YesYesYesYesYes
SQRT()YesYesYesYesNo*
SIGN()YesYesYesYesNo
LN()YesYesUse LOG()YesNo
LOG10()Use LOG()YesYesUse LOG(10,x)No
EXP()YesYesYesYesNo
TRUNC(n, d)YesTRUNCATE()ROUND(n,d,1)YesNo
RANDOM()RANDOM()RAND()RAND()DBMS_RANDOM.VALUERANDOM()

*SQLite has limited built-in math functions but supports them via extensions.

Quick Reference

TaskFunctionExampleResult
Round to N decimalsROUND(n, d)ROUND(3.456, 2)3.46
Round up to integerCEIL(n)CEIL(3.2)4
Round down to integerFLOOR(n)FLOOR(3.8)3
Absolute valueABS(n)ABS(-42)42
RemainderMOD(a, b)MOD(10, 3)1
ExponentPOWER(b, e)POWER(2, 10)1024
Square rootSQRT(n)SQRT(144)12
Sign detectionSIGN(n)SIGN(-5)-1
Safe divisiona / NULLIF(b, 0)10 / NULLIF(0, 0)NULL
Force decimal divisiona / b::DECIMAL7.0 / 23.5

Summary

SQL numeric functions provide a complete mathematical toolkit for working with numbers directly in your queries. From simple rounding to complex financial calculations, these functions let you process numeric data where it lives without round-tripping through application code.

Key takeaways:

  • Arithmetic operators (+, -, *, /, %) work directly in SELECT, WHERE, and other clauses. Watch out for integer division in PostgreSQL, SQL Server, and SQLite, where dividing two integers truncates the result.
  • ROUND is your most-used numeric function. Round only final results, not intermediate values, to avoid cumulative errors. Be aware of banker's rounding in PostgreSQL.
  • CEIL rounds up, FLOOR rounds down. Use CEIL for "how many containers do I need?" calculations and FLOOR for bucket/tier grouping.
  • ABS strips the sign from a number. Use it for distance calculations and variance analysis.
  • MOD returns the remainder after division. Use it for even/odd checks, distributing items across groups, and cyclic patterns.
  • POWER and SQRT handle exponentiation and roots. Essential for compound interest, distance calculations, and statistical formulas.
  • Always protect against division by zero using NULLIF(divisor, 0).
  • Use DECIMAL for money, never FLOAT. Floating-point arithmetic introduces rounding errors that compound in financial calculations.
  • Use parentheses in complex expressions to make operator precedence explicit and prevent subtle bugs.

Master these functions and you can perform virtually any numeric calculation directly in SQL, keeping your data processing efficient and your application code clean.