Skip to main content
eLearner.app
Module 6 · Lesson 3 of 423/57 in the course~10 min
Module lessons (3/4)

Numeric functions

PostgreSQL has all the numeric functions you would expect — plus a few type pitfalls that are worth knowing right away.

The most used functions

SQL
ROUND(price, 2)     -- arrotonda a 2 decimali (banker's rounding "half to even")
CEIL(price)         -- arrotonda per eccesso (verso +∞)
FLOOR(price)        -- arrotonda per difetto (verso −∞)
ABS(-5)             -- 5  (valore assoluto)
MOD(10, 3)          -- 1  (resto della divisione)  — anche 10 % 3
POWER(2, 10)        -- 1024
SQRT(16)            -- 4

ROUND(number, decimals) only works if number is NUMERIC (not DOUBLE PRECISION). In our dataset products.price is NUMERIC(10,2), so we're already set.

Integer vs decimal division

The classic pitfall:

SQL
SELECT 1 / 2;          -- 0  (entrambi interi → divisione intera!)
SELECT 1.0 / 2;        -- 0.5
SELECT 1::numeric / 2; -- 0.50000000000000000000

When you divide two INTEGER columns you get an INTEGER. To avoid truncation, cast one of them to NUMERIC or multiply by 1.0:

SQL
-- Sbagliato: percentuale sempre 0 finché numeratore < denominatore
SELECT shipped / total FROM …;

-- Corretto:
SELECT shipped::numeric / total FROM …;
SELECT ROUND(shipped * 100.0 / total, 2) AS percentage FROM …;

Examples on the dataset

SQL
-- Prezzo scontato del 10%, arrotondato a 2 decimali:
SELECT name,
       price,
       ROUND(price * 0.9, 2) AS discounted_price
FROM   products
ORDER BY id;

-- Prezzo "psicologico" sempre arrotondato per eccesso al multiplo di 1:
SELECT name, CEIL(price) AS rounded_price
FROM   products
WHERE  price < 100
ORDER BY price;

Try it

Exercise#sql.m6.l3.e1
Attempts: 0Loading…

For each product show name, price (original price) and discounted_price (price reduced by 10%, rounded to 2 decimals). Order by id.

Loading editor…
Show hint

Reduce price by 10% by multiplying by 0.9, then round with ROUND(..., 2).

Solution available after 3 attempts

Review exercise

Exercise#sql.m6.l3.e2
Attempts: 0Loading…

For each delivered order (status = 'delivered'), show id and wait_days as the integer number of days (rounded down) between ordered_at and shipped_at. Order by wait_days descending, then by id.

Loading editor…
Show hint

shipped_at - ordered_at returns an INTERVAL; EXTRACT(EPOCH FROM …) turns it into seconds; divide by 86400 (seconds in a day) and take the FLOOR.

Solution available after 3 attempts