Уроки модуля (3/4)
Числовые функции
PostgreSQL имеет все числовые функции, которые вы ожидаете, плюс несколько укажите подводные камни, о которых стоит знать сразу.
Наиболее часто используемые функции
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) -- 4ROUND(number, decimals) работает, только если number имеет значение NUMERIC (не
DOUBLE PRECISION). В нашем наборе данных products.price — это NUMERIC(10,2),
так что мы уже готовы.
Целое число против десятичного деления
Классическая ловушка:
SELECT 1 / 2; -- 0 (entrambi interi → divisione intera!)
SELECT 1.0 / 2; -- 0.5
SELECT 1::numeric / 2; -- 0.50000000000000000000Когда вы разделите два столбца INTEGER, вы получите INTEGER. Чтобы избежать
усечение, приведите одно из них к NUMERIC или умножьте на 1.0:
-- 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 …;Примеры в наборе данных
-- 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;Попробуйте это
Для каждого продукта отображается название, цена (исходная цена) и скидка_цена (цена уменьшена на 10 % и округлена до 2 десятичных знаков). Заказ по идентификатору.
Показать подсказку
Уменьшите цену на 10 %, умножив ее на 0,9, а затем округлив с помощью ROUND(..., 2).
Решение доступно после 3 попыток
Обзор упражнения
Для каждого доставленного заказа (статус = «доставлен») покажите id и wait_days как целое число дней (округленное вниз) между order_at и доставленным_at. Упорядочить по убыванию числа дней ожидания, затем по идентификатору.
Показать подсказку
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.
Решение доступно после 3 попыток