TRUNC в SQL — это функция, которая отрезает лишние цифры у числа без округления.
Она не думает: «Ближе к 3 или к 4?»
Она просто берёт число и срезает всё, что не должно остаться.
Например:
| Число |
TRUNC |
| 3.99 |
3 |
| 3.01 |
3 |
| 2.50 |
2 |
| -3.99 |
-3 |
Главная идея простая:
TRUNC не округляет число. Он отбрасывает лишнюю часть.
Это особенно важно в расчётах, где число не должно «перепрыгнуть» на следующий разряд: комиссии, лимиты, технические корзины, финансовые правила, расчёт бонусов, процентов и скидок.
Чем TRUNC отличается от ROUND
Начнём с самого понятного сравнения.
ROUND округляет число по правилам округления.
TRUNC просто срезает лишнее.
SELECT
round(3.99) AS rounded_a,
trunc(3.99) AS truncated_a,
round(2.50) AS rounded_b,
trunc(2.50) AS truncated_b;
Результат будет примерно такой:
| rounded_a |
truncated_a |
rounded_b |
truncated_b |
| 4 |
3 |
3 |
2 |
ROUND(3.99) превращает число в 4, потому что 3.99 ближе к 4.
А TRUNC(3.99) возвращает 3, потому что всё после точки просто отбрасывается.
Можно представить так:
ROUND — «округли как правильно по математике»;
TRUNC — «срежь лишнее и ничего не улучшай».
Базовый синтаксис
В PostgreSQL простая форма выглядит так:
SELECT trunc(123.4567) AS result;
Результат:
Функция убрала дробную часть .4567 и оставила только целую часть.
Ещё несколько примеров:
SELECT
trunc(3.99) AS a,
trunc(3.01) AS b,
trunc(-3.99) AS c,
trunc(2.50) AS d;
Результат:
Обратите внимание на отрицательное число: trunc(-3.99) вернул -3, а не -4.
Почему так? Потому что TRUNC отбрасывает дробную часть в сторону нуля.
TRUNC двигается к нулю
Это одна из самых важных деталей.
Для положительных чисел всё интуитивно:
| Число |
Результат |
| 3.99 |
3 |
| 3.10 |
3 |
| 3.00 |
3 |
А вот с отрицательными числами новички часто ошибаются.
SELECT
trunc(-3.99) AS a,
trunc(-3.10) AS b,
trunc(-3.00) AS c;
Результат:
TRUNC не делает число «ещё меньше». Он просто срезает дробную часть.
То есть -3.99 превращается в -3, потому что -3 ближе к нулю, чем -4.
TRUNC с количеством знаков после запятой
У TRUNC может быть второй аргумент. Он показывает, сколько знаков после запятой нужно оставить.
SELECT
trunc(123.4567, 2) AS two_digits,
trunc(123.4567, 1) AS one_digit,
trunc(123.4567, 0) AS zero_digits;
Результат:
| two_digits |
one_digit |
zero_digits |
| 123.45 |
123.4 |
123 |
Смысл такой:
trunc(123.4567, 2) оставляет два знака после запятой;
trunc(123.4567, 1) оставляет один знак;
trunc(123.4567, 0) оставляет только целую часть.
И снова никакого округления.
123.4567 при усечении до двух знаков становится 123.45, а не 123.46.
Отрицательный второй аргумент
Второй аргумент может быть отрицательным.
Тогда TRUNC начинает срезать разряды уже слева от запятой: единицы, десятки, сотни.
SELECT
trunc(123.4567, -1) AS tens,
trunc(123.4567, -2) AS hundreds,
trunc(9876.543, -3) AS thousands;
Результат:
| tens |
hundreds |
thousands |
| 120 |
100 |
9000 |
Как это читать:
-1 срезает до десятков;
-2 срезает до сотен;
-3 срезает до тысяч.
Это удобно, когда нужно разложить значения по грубым корзинам.
Например, зарплату 4999 можно отнести к корзине 4900, а не округлить до 5000.
SELECT
name,
salary,
trunc(salary, -2) AS salary_bucket
FROM employees
ORDER BY salary DESC;
Если у сотрудника зарплата 4999, то salary_bucket будет 4900.
TRUNC не дотягивает число вверх. Он режет.
Пример: корзины для сумм заказов
Допустим, есть таблица заказов:
CREATE TABLE orders (
id bigint PRIMARY KEY,
user_id bigint NOT NULL,
amount numeric NOT NULL,
status text NOT NULL
);
Хотим сгруппировать оплаченные заказы по сотням: 100, 200, 300, 400 и так далее.
SELECT
trunc(amount, -2) AS amount_bucket,
count(*) AS orders_count
FROM orders
WHERE status = 'paid'
GROUP BY trunc(amount, -2)
ORDER BY amount_bucket;
Если суммы такие:
| amount |
| 120 |
| 180 |
| 249 |
| 310 |
| 399 |
То корзины будут такими:
| amount |
amount_bucket |
| 120 |
100 |
| 180 |
100 |
| 249 |
200 |
| 310 |
300 |
| 399 |
300 |
Это не округление до ближайшей сотни. Это именно усечение.
399 попадёт в 300, а не в 400.
TRUNC против FLOOR
Для положительных чисел TRUNC и FLOOR часто дают одинаковый результат.
SELECT
floor(3.8) AS floor_value,
trunc(3.8) AS trunc_value;
Результат:
| floor_value |
trunc_value |
| 3 |
3 |
Но на отрицательных числах начинается важное отличие.
FLOOR округляет вниз, то есть в сторону минус бесконечности.
TRUNC отбрасывает дробную часть в сторону нуля.
SELECT
floor(-3.2) AS floor_negative,
trunc(-3.2) AS trunc_negative,
floor(3.2) AS floor_positive,
trunc(3.2) AS trunc_positive;
Результат:
| floor_negative |
trunc_negative |
floor_positive |
trunc_positive |
| -4 |
-3 |
3 |
3 |
Вот здесь легко поймать неприятный баг.
Если у вас есть возвраты, списания или корректировки с отрицательными суммами, FLOOR и TRUNC дадут разные значения.
SELECT
id,
amount,
floor(amount) AS whole_floor,
trunc(amount) AS whole_trunc
FROM orders
WHERE amount < 0;
Для суммы -15.30 результат будет таким:
| amount |
whole_floor |
whole_trunc |
| -15.30 |
-16 |
-15 |
Если по бизнес-логике нужно именно отбросить дробную часть, берите TRUNC.
Если нужно округлить вниз по числовой оси, берите FLOOR.
Это разные операции.
TRUNC против CEIL
Есть ещё функция CEIL или CEILING. Она округляет число вверх.
SELECT
trunc(4.1) AS truncated_value,
floor(4.1) AS floor_value,
ceil(4.1) AS ceil_value;
Результат:
| truncated_value |
floor_value |
ceil_value |
| 4 |
4 |
5 |
Для положительного числа 4.1:
TRUNC даёт 4;
FLOOR даёт 4;
CEIL даёт 5.
А для отрицательного числа:
SELECT
trunc(-4.1) AS truncated_value,
floor(-4.1) AS floor_value,
ceil(-4.1) AS ceil_value;
Результат:
| truncated_value |
floor_value |
ceil_value |
| -4 |
-5 |
-4 |
Поэтому при работе с отрицательными числами всегда проверяйте, что именно вы хотите: срезать дробь, округлить вниз или округлить вверх.
Где TRUNC полезен на практике
TRUNC нужен там, где округление может изменить смысл числа.
Например, у пользователя есть лимит 1000. После расчёта получилось 999.99.
Если использовать ROUND, можно случайно получить 1000.
Если использовать TRUNC, значение останется 999.
Такое поведение может быть важно в правилах:
- комиссий;
- процентов;
- лимитов;
- бонусов;
- технических бакетов;
- расчёта тарифа;
- финансовых ограничений;
- промежуточных аналитических метрик.
Главная мысль:
TRUNC используют, когда число не должно увеличиться из-за округления.
Пример: комиссия без округления вверх
Допустим, платформа берёт комиссию 2.9% с оплаченных заказов. По договору комиссия должна считаться с точностью до копеек, но без округления вверх.
SELECT
u.id,
sum(o.amount) AS gross_amount,
round(sum(o.amount) * 0.029, 2) AS fee_rounded,
trunc(sum(o.amount) * 0.029, 2) AS fee_truncated
FROM users u
JOIN orders o ON o.user_id = u.id
WHERE o.status = 'paid'
GROUP BY u.id;
Разница может быть небольшой на одной операции, но на тысячах операций она накапливается.
Например:
| value |
ROUND(value, 2) |
TRUNC(value, 2) |
| 2.575 |
2.58 |
2.57 |
| 10.999 |
11.00 |
10.99 |
| 99.995 |
100.00 |
99.99 |
ROUND может поднять число.
TRUNC никогда не поднимает его из-за отброшенных цифр.
Именно поэтому правило округления или усечения должно быть прописано в требованиях. Для денег это не вкусовщина, а часть бизнес-логики.
Важное правило для денег
С деньгами лучше работать через точные числовые типы, например numeric.
Не стоит без необходимости считать финансовые значения через float или double precision.
Причина в том, что числа с плавающей точкой хранятся в двоичном виде, и некоторые десятичные дроби не могут быть представлены идеально точно.
Например, значение вроде 0.29 внутри может храниться как число чуть меньше или чуть больше. Для технических расчётов это нормально, но для денег может дать неприятные сюрпризы.
Хороший вариант:
SELECT
trunc(amount::numeric * 0.029, 2) AS fee
FROM orders
WHERE status = 'paid';
Если колонка amount уже имеет тип numeric, дополнительное приведение может быть не нужно. Но сама идея остаётся: для денег лучше выбирать точную арифметику.
Усечение не всегда правильно
Важно не превращать TRUNC в универсальную замену ROUND.
Во многих бухгалтерских и финансовых задачах как раз требуется обычное округление.
Например, если в требованиях сказано:
«Округлять до двух знаков после запятой по стандартным правилам».
Тогда нужен ROUND, а не TRUNC.
SELECT
round(amount, 2) AS amount_rounded
FROM orders;
Если сказано:
«Отбрасывать лишние знаки без округления».
Тогда нужен TRUNC.
SELECT
trunc(amount, 2) AS amount_truncated
FROM orders;
Не угадывайте. Для денег, комиссий и лимитов правило нужно уточнять и фиксировать явно.
Пример: сравнение ROUND и TRUNC в отчёте
Допустим, мы хотим показать сумму заказов пользователя и комиссию.
SELECT
user_id,
sum(amount) AS gross_amount,
sum(amount) * 0.029 AS raw_fee,
round(sum(amount) * 0.029, 2) AS rounded_fee,
trunc(sum(amount) * 0.029, 2) AS truncated_fee
FROM orders
WHERE status = 'paid'
GROUP BY user_id
ORDER BY user_id;
Такой отчёт полезен для проверки: можно сразу увидеть исходную комиссию, округлённую комиссию и усечённую комиссию.
Если бизнес требует усечение, итоговую колонку берём из truncated_fee.
Если требует округление, берём из rounded_fee.
TRUNC и тип результата
В PostgreSQL поведение зависит от типа входного значения.
Для numeric результат будет numeric.
SELECT
trunc(123.456::numeric, 2) AS result;
Для double precision есть форма trunc(x), которая возвращает значение с плавающей точкой.
На практике для начинающего важнее запомнить не типы, а смысл:
Если нужна финансовая точность, работайте с numeric. Если это технические измерения вроде latency или координат, иногда допустимы вещественные типы.
TRUNC в MySQL
В MySQL функция называется не TRUNC, а TRUNCATE.
И второй аргумент там обязателен.
SELECT
truncate(123.4567, 2) AS two_digits,
truncate(123.4567, 0) AS zero_digits;
Результат:
| two_digits |
zero_digits |
| 123.45 |
123 |
В MySQL можно использовать и отрицательный второй аргумент:
SELECT
truncate(123.4567, -1) AS tens,
truncate(123.4567, -2) AS hundreds;
Результат:
Важно не путать функцию TRUNCATE с командой TRUNCATE TABLE.
TRUNCATE TABLE orders;
Это уже совсем другая операция. Она очищает таблицу, а не работает с числом.
Название похоже, смысл совершенно другой.
TRUNC в ClickHouse
В ClickHouse можно встретить функции trunc и truncate.
Примерно смысл тот же: отбросить дробную часть или лишние знаки без обычного округления.
SELECT
trunc(123.4567) AS integer_part,
truncate(123.4567, 2) AS two_digits;
При переносе запроса между PostgreSQL, MySQL и ClickHouse проверяйте название функции и правила аргументов. Идея одна и та же, но синтаксис может отличаться.
Частая ошибка: использовать TRUNC там, где нужен ROUND
Допустим, в отчёте нужно показать средний чек до двух знаков после запятой.
SELECT
trunc(avg(amount), 2) AS avg_amount
FROM orders
WHERE status = 'paid';
Технически запрос работает. Но вопрос: правильно ли это по смыслу?
Если отчёт должен показывать обычное округление, нужно писать так:
SELECT
round(avg(amount), 2) AS avg_amount
FROM orders
WHERE status = 'paid';
TRUNC систематически срезает хвост и не даёт числу подняться. Поэтому он может немного занижать результат.
Для одной строки разница почти незаметна. Для большого отчёта, финансовой выгрузки или расчёта комиссии эта разница может стать существенной.
Частая ошибка: думать, что TRUNC и FLOOR одинаковые
Для положительных чисел они часто совпадают, поэтому возникает ложное ощущение, что это одно и то же.
Но на отрицательных значениях они расходятся:
SELECT
amount,
trunc(amount) AS truncated_value,
floor(amount) AS floor_value
FROM transactions
WHERE amount < 0;
Если в таблице есть возвраты, штрафы, корректировки или отрицательные балансы, эта разница может повлиять на итоговые цифры.
Запоминаем:
TRUNC режет к нулю;
FLOOR округляет вниз;
CEIL округляет вверх;
ROUND округляет по правилам округления.
Когда выбирать TRUNC
Используйте TRUNC, когда правило звучит так:
«Оставить нужное количество знаков и отбросить всё остальное».
Примеры:
- комиссия не должна округляться вверх;
- лимит нельзя случайно увеличить;
- значение нужно отнести к нижней корзине;
- дробная часть технически не нужна;
- число должно быть симметрично усечено для плюса и минуса;
- в требованиях прямо написано «без округления».
Если же правило звучит как:
«Округлить до ближайшего значения».
Тогда используйте ROUND.
Главное
TRUNC в SQL отбрасывает дробную часть числа без округления.
trunc(3.99) вернёт 3, а не 4.
trunc(-3.99) вернёт -3, потому что усечение идёт к нулю.
С помощью второго аргумента можно оставить нужное количество знаков после запятой:
SELECT trunc(123.4567, 2) AS result;
Результат будет 123.45, а не 123.46.
Отрицательный второй аргумент срезает разряды слева от запятой: десятки, сотни, тысячи.
TRUNC особенно полезен в расчётах комиссий, лимитов и технических корзин, где число не должно увеличиваться из-за округления.
Не путайте TRUNC с ROUND, FLOOR и CEIL: это разные функции с разным смыслом, особенно на отрицательных числах.
В PostgreSQL используется TRUNC, в MySQL — TRUNCATE, а команда TRUNCATE TABLE вообще не про числа, а про очистку таблицы.
Главное правило: если нужно именно срезать лишние цифры, используйте TRUNC. Если нужно округлить по правилам математики, используйте ROUND.
TRUNCв SQL — это функция, которая отрезает лишние цифры у числа без округления.Она не думает: «Ближе к 3 или к 4?»
Она просто берёт число и срезает всё, что не должно остаться.
Например:
TRUNCГлавная идея простая:
Это особенно важно в расчётах, где число не должно «перепрыгнуть» на следующий разряд: комиссии, лимиты, технические корзины, финансовые правила, расчёт бонусов, процентов и скидок.
Чем TRUNC отличается от ROUND
Начнём с самого понятного сравнения.
ROUNDокругляет число по правилам округления.TRUNCпросто срезает лишнее.SELECT round(3.99) AS rounded_a, trunc(3.99) AS truncated_a, round(2.50) AS rounded_b, trunc(2.50) AS truncated_b;Результат будет примерно такой:
ROUND(3.99)превращает число в4, потому что3.99ближе к4.А
TRUNC(3.99)возвращает3, потому что всё после точки просто отбрасывается.Можно представить так:
ROUND— «округли как правильно по математике»;TRUNC— «срежь лишнее и ничего не улучшай».Базовый синтаксис
В PostgreSQL простая форма выглядит так:
SELECT trunc(123.4567) AS result;Результат:
Функция убрала дробную часть
.4567и оставила только целую часть.Ещё несколько примеров:
SELECT trunc(3.99) AS a, trunc(3.01) AS b, trunc(-3.99) AS c, trunc(2.50) AS d;Результат:
Обратите внимание на отрицательное число:
trunc(-3.99)вернул-3, а не-4.Почему так? Потому что
TRUNCотбрасывает дробную часть в сторону нуля.TRUNC двигается к нулю
Это одна из самых важных деталей.
Для положительных чисел всё интуитивно:
А вот с отрицательными числами новички часто ошибаются.
SELECT trunc(-3.99) AS a, trunc(-3.10) AS b, trunc(-3.00) AS c;Результат:
TRUNCне делает число «ещё меньше». Он просто срезает дробную часть.То есть
-3.99превращается в-3, потому что-3ближе к нулю, чем-4.TRUNC с количеством знаков после запятой
У
TRUNCможет быть второй аргумент. Он показывает, сколько знаков после запятой нужно оставить.SELECT trunc(123.4567, 2) AS two_digits, trunc(123.4567, 1) AS one_digit, trunc(123.4567, 0) AS zero_digits;Результат:
Смысл такой:
trunc(123.4567, 2)оставляет два знака после запятой;trunc(123.4567, 1)оставляет один знак;trunc(123.4567, 0)оставляет только целую часть.И снова никакого округления.
123.4567при усечении до двух знаков становится123.45, а не123.46.Отрицательный второй аргумент
Второй аргумент может быть отрицательным.
Тогда
TRUNCначинает срезать разряды уже слева от запятой: единицы, десятки, сотни.SELECT trunc(123.4567, -1) AS tens, trunc(123.4567, -2) AS hundreds, trunc(9876.543, -3) AS thousands;Результат:
Как это читать:
-1срезает до десятков;-2срезает до сотен;-3срезает до тысяч.Это удобно, когда нужно разложить значения по грубым корзинам.
Например, зарплату
4999можно отнести к корзине4900, а не округлить до5000.SELECT name, salary, trunc(salary, -2) AS salary_bucket FROM employees ORDER BY salary DESC;Если у сотрудника зарплата
4999, тоsalary_bucketбудет4900.TRUNCне дотягивает число вверх. Он режет.Пример: корзины для сумм заказов
Допустим, есть таблица заказов:
CREATE TABLE orders ( id bigint PRIMARY KEY, user_id bigint NOT NULL, amount numeric NOT NULL, status text NOT NULL );Хотим сгруппировать оплаченные заказы по сотням:
100,200,300,400и так далее.SELECT trunc(amount, -2) AS amount_bucket, count(*) AS orders_count FROM orders WHERE status = 'paid' GROUP BY trunc(amount, -2) ORDER BY amount_bucket;Если суммы такие:
То корзины будут такими:
Это не округление до ближайшей сотни. Это именно усечение.
399попадёт в300, а не в400.TRUNC против FLOOR
Для положительных чисел
TRUNCиFLOORчасто дают одинаковый результат.SELECT floor(3.8) AS floor_value, trunc(3.8) AS trunc_value;Результат:
Но на отрицательных числах начинается важное отличие.
FLOORокругляет вниз, то есть в сторону минус бесконечности.TRUNCотбрасывает дробную часть в сторону нуля.SELECT floor(-3.2) AS floor_negative, trunc(-3.2) AS trunc_negative, floor(3.2) AS floor_positive, trunc(3.2) AS trunc_positive;Результат:
Вот здесь легко поймать неприятный баг.
Если у вас есть возвраты, списания или корректировки с отрицательными суммами,
FLOORиTRUNCдадут разные значения.SELECT id, amount, floor(amount) AS whole_floor, trunc(amount) AS whole_trunc FROM orders WHERE amount < 0;Для суммы
-15.30результат будет таким:Если по бизнес-логике нужно именно отбросить дробную часть, берите
TRUNC.Если нужно округлить вниз по числовой оси, берите
FLOOR.Это разные операции.
TRUNC против CEIL
Есть ещё функция
CEILилиCEILING. Она округляет число вверх.SELECT trunc(4.1) AS truncated_value, floor(4.1) AS floor_value, ceil(4.1) AS ceil_value;Результат:
Для положительного числа
4.1:TRUNCдаёт4;FLOORдаёт4;CEILдаёт5.А для отрицательного числа:
SELECT trunc(-4.1) AS truncated_value, floor(-4.1) AS floor_value, ceil(-4.1) AS ceil_value;Результат:
Поэтому при работе с отрицательными числами всегда проверяйте, что именно вы хотите: срезать дробь, округлить вниз или округлить вверх.
Где TRUNC полезен на практике
TRUNCнужен там, где округление может изменить смысл числа.Например, у пользователя есть лимит
1000. После расчёта получилось999.99.Если использовать
ROUND, можно случайно получить1000.Если использовать
TRUNC, значение останется999.Такое поведение может быть важно в правилах:
Главная мысль:
Пример: комиссия без округления вверх
Допустим, платформа берёт комиссию
2.9%с оплаченных заказов. По договору комиссия должна считаться с точностью до копеек, но без округления вверх.SELECT u.id, sum(o.amount) AS gross_amount, round(sum(o.amount) * 0.029, 2) AS fee_rounded, trunc(sum(o.amount) * 0.029, 2) AS fee_truncated FROM users u JOIN orders o ON o.user_id = u.id WHERE o.status = 'paid' GROUP BY u.id;Разница может быть небольшой на одной операции, но на тысячах операций она накапливается.
Например:
ROUND(value, 2)TRUNC(value, 2)ROUNDможет поднять число.TRUNCникогда не поднимает его из-за отброшенных цифр.Именно поэтому правило округления или усечения должно быть прописано в требованиях. Для денег это не вкусовщина, а часть бизнес-логики.
Важное правило для денег
С деньгами лучше работать через точные числовые типы, например
numeric.Не стоит без необходимости считать финансовые значения через
floatилиdouble precision.Причина в том, что числа с плавающей точкой хранятся в двоичном виде, и некоторые десятичные дроби не могут быть представлены идеально точно.
Например, значение вроде
0.29внутри может храниться как число чуть меньше или чуть больше. Для технических расчётов это нормально, но для денег может дать неприятные сюрпризы.Хороший вариант:
SELECT trunc(amount::numeric * 0.029, 2) AS fee FROM orders WHERE status = 'paid';Если колонка
amountуже имеет типnumeric, дополнительное приведение может быть не нужно. Но сама идея остаётся: для денег лучше выбирать точную арифметику.Усечение не всегда правильно
Важно не превращать
TRUNCв универсальную заменуROUND.Во многих бухгалтерских и финансовых задачах как раз требуется обычное округление.
Например, если в требованиях сказано:
Тогда нужен
ROUND, а неTRUNC.SELECT round(amount, 2) AS amount_rounded FROM orders;Если сказано:
Тогда нужен
TRUNC.SELECT trunc(amount, 2) AS amount_truncated FROM orders;Не угадывайте. Для денег, комиссий и лимитов правило нужно уточнять и фиксировать явно.
Пример: сравнение ROUND и TRUNC в отчёте
Допустим, мы хотим показать сумму заказов пользователя и комиссию.
SELECT user_id, sum(amount) AS gross_amount, sum(amount) * 0.029 AS raw_fee, round(sum(amount) * 0.029, 2) AS rounded_fee, trunc(sum(amount) * 0.029, 2) AS truncated_fee FROM orders WHERE status = 'paid' GROUP BY user_id ORDER BY user_id;Такой отчёт полезен для проверки: можно сразу увидеть исходную комиссию, округлённую комиссию и усечённую комиссию.
Если бизнес требует усечение, итоговую колонку берём из
truncated_fee.Если требует округление, берём из
rounded_fee.TRUNC и тип результата
В PostgreSQL поведение зависит от типа входного значения.
Для
numericрезультат будетnumeric.SELECT trunc(123.456::numeric, 2) AS result;Для
double precisionесть формаtrunc(x), которая возвращает значение с плавающей точкой.На практике для начинающего важнее запомнить не типы, а смысл:
TRUNC в MySQL
В MySQL функция называется не
TRUNC, аTRUNCATE.И второй аргумент там обязателен.
SELECT truncate(123.4567, 2) AS two_digits, truncate(123.4567, 0) AS zero_digits;Результат:
В MySQL можно использовать и отрицательный второй аргумент:
SELECT truncate(123.4567, -1) AS tens, truncate(123.4567, -2) AS hundreds;Результат:
Важно не путать функцию
TRUNCATEс командойTRUNCATE TABLE.TRUNCATE TABLE orders;Это уже совсем другая операция. Она очищает таблицу, а не работает с числом.
Название похоже, смысл совершенно другой.
TRUNC в ClickHouse
В ClickHouse можно встретить функции
truncиtruncate.Примерно смысл тот же: отбросить дробную часть или лишние знаки без обычного округления.
SELECT trunc(123.4567) AS integer_part, truncate(123.4567, 2) AS two_digits;При переносе запроса между PostgreSQL, MySQL и ClickHouse проверяйте название функции и правила аргументов. Идея одна и та же, но синтаксис может отличаться.
Частая ошибка: использовать TRUNC там, где нужен ROUND
Допустим, в отчёте нужно показать средний чек до двух знаков после запятой.
SELECT trunc(avg(amount), 2) AS avg_amount FROM orders WHERE status = 'paid';Технически запрос работает. Но вопрос: правильно ли это по смыслу?
Если отчёт должен показывать обычное округление, нужно писать так:
SELECT round(avg(amount), 2) AS avg_amount FROM orders WHERE status = 'paid';TRUNCсистематически срезает хвост и не даёт числу подняться. Поэтому он может немного занижать результат.Для одной строки разница почти незаметна. Для большого отчёта, финансовой выгрузки или расчёта комиссии эта разница может стать существенной.
Частая ошибка: думать, что TRUNC и FLOOR одинаковые
Для положительных чисел они часто совпадают, поэтому возникает ложное ощущение, что это одно и то же.
Но на отрицательных значениях они расходятся:
SELECT amount, trunc(amount) AS truncated_value, floor(amount) AS floor_value FROM transactions WHERE amount < 0;Если в таблице есть возвраты, штрафы, корректировки или отрицательные балансы, эта разница может повлиять на итоговые цифры.
Запоминаем:
TRUNCрежет к нулю;FLOORокругляет вниз;CEILокругляет вверх;ROUNDокругляет по правилам округления.Когда выбирать TRUNC
Используйте
TRUNC, когда правило звучит так:Примеры:
Если же правило звучит как:
Тогда используйте
ROUND.Главное
TRUNCв SQL отбрасывает дробную часть числа без округления.trunc(3.99)вернёт3, а не4.trunc(-3.99)вернёт-3, потому что усечение идёт к нулю.С помощью второго аргумента можно оставить нужное количество знаков после запятой:
SELECT trunc(123.4567, 2) AS result;Результат будет
123.45, а не123.46.Отрицательный второй аргумент срезает разряды слева от запятой: десятки, сотни, тысячи.
TRUNCособенно полезен в расчётах комиссий, лимитов и технических корзин, где число не должно увеличиваться из-за округления.Не путайте
TRUNCсROUND,FLOORиCEIL: это разные функции с разным смыслом, особенно на отрицательных числах.В PostgreSQL используется
TRUNC, в MySQL —TRUNCATE, а командаTRUNCATE TABLEвообще не про числа, а про очистку таблицы.Главное правило: если нужно именно срезать лишние цифры, используйте
TRUNC. Если нужно округлить по правилам математики, используйтеROUND.