Round a number to N decimal places
Short answer: ROUND(value, n) rounds to n decimal places, and works on every major engine. CEIL(value) rounds up to the next integer; FLOOR(value) rounds down; TRUNC(value, n) truncates without rounding. Watch the rounding mode: most engines use banker's rounding (round half to even) for floats and round half away from zero for decimals, so they can produce different results for the same input.
Canonical SQL #
SELECT
ROUND(123.456, 2) AS round_2_decimals, -- 123.46
ROUND(123.456, 0) AS round_to_integer, -- 123
ROUND(123.456, -1) AS round_to_tens, -- 120
CEIL(123.456) AS round_up, -- 124
FLOOR(123.456) AS round_down, -- 123
TRUNC(123.456, 2) AS truncate_2_decimals; -- 123.45 — Postgres / Oracle / Snowflake (no 2-arg TRUNC on DuckDB / MySQL / SQL Server)Example #
Common patterns #
-- Round money to 2 decimals (display-ready).
SELECT ROUND(SUM(amount), 2) AS total FROM orders;
-- Percentage with 1 decimal (e.g., 23.4%).
SELECT ROUND((COUNT(*) FILTER (WHERE status = 'paid')::DECIMAL / COUNT(*)) * 100, 1) AS pct_paid
FROM orders;
-- Round to nearest 100 (or any unit).
SELECT ROUND(price / 100) * 100 AS price_to_nearest_100 FROM products;
-- Round up to next multiple of 5.
SELECT CEIL(value / 5.0) * 5 AS next_5 FROM measurements;
-- Truncate (cut off, no rounding).
SELECT TRUNC(value, 2) FROM measurements; -- Postgres / Oracle / Snowflake
SELECT FLOOR(value * 100) / 100 FROM measurements; -- portable equivalent
-- Convert float to N-decimal-place DECIMAL for storage.
SELECT CAST(amount AS DECIMAL(10, 2)) FROM orders; -- rounds during castDialect notes #
- Postgres:
ROUND(numeric, int); onlynumerictypes support a precision argument.ROUND(double precision)(no second arg) rounds to the nearest integer; tie-breaking is platform-dependent (usually banker's rounding). To round aDOUBLEto N places: cast first (ROUND(value::numeric, 2)). - MySQL:
ROUND(value, n). Default mode is "round half away from zero" but depends onSQL_MODE.TRUNCATE(value, n)instead ofTRUNC. - SQL Server:
ROUND(value, n)rounds;ROUND(value, n, 1)truncates (third arg = truncate flag).CEILING(notCEIL). - Oracle:
ROUND,TRUNC,CEIL,FLOORall standard.ROUND(value, -2)for "round to nearest 100." - Snowflake:
ROUND(value, n). Rounds ties away from zero by default; pass'HALF_TO_EVEN'as the third argument for banker's rounding.TRUNC(value, n)truncates. - BigQuery:
ROUND(value, n).TRUNC(value, n)truncates. Ties round away from zero by default;ROUND(x, n, 'ROUND_HALF_EVEN')onNUMERIC/BIGNUMERICfor banker's rounding. - DuckDB:
ROUND(value, n),CEIL,FLOORavailable;TRUNCtakes no precision argument, so truncate to N places withTRUNC(value * 100) / 100.ROUND_EVEN(value, n)for banker's rounding. - SQLite:
ROUND(value, n). No nativeTRUNCorCEIL/FLOORuntil 3.35+.
**Round at the display layer, not at every step of the calculation.** ROUND(SUM(amount), 2) after the aggregation is right; SUM(ROUND(amount, 2)) per row before the aggregation can produce a total that's off by a cent on every batch (rounding errors accumulate). The pattern: keep full precision through every calculation; round only when emitting to a human-readable number. Especially relevant for money and ratios; see DECIMAL vs FLOAT for the related precision question.