SIGN и TRUNC в SQL: знак числа и усечение дробной части

SIGN(x) возвращает знак числа: −1 для отрицательных, 0 для нуля и 1 для положительных — удобно классифицировать рост и падение. TRUNC(x) отсекает дробную часть в сторону нуля, не округляя: TRUNC(9.99) = 9, TRUNC(−9.99) = −9. По диалектам есть важные различия: SIGN есть везде (в SQLite — в математическом расширении), а вот TRUNC в PostgreSQL умеет второй аргумент (число знаков), в MySQL функция называется TRUNCATE(x, d) и требует два аргумента, а в SQLite trunc() работает только с одним.

Синтаксис

SIGN(numeric_expression) -- -1, 0 или 1 TRUNC(numeric_expression [, decimals]) -- усечение к нулю; в MySQL это TRUNCATE(x, d)

Примеры использования

Пример 1: Направление изменения через SIGN

SELECT event_id,
       delta,
       SIGN(delta) AS direction
FROM events
LIMIT 3;

Результат:

event_id | delta | direction
   10    |    45 |     1
   11    |     0 |     0
   12    |   -18 |    -1

Пример 2: TRUNC против ROUND на суммах платежей

SELECT amount,
       TRUNC(amount, 1) AS truncated,
       ROUND(amount, 1) AS rounded
FROM payments
LIMIT 3;

Результат:

amount | truncated | rounded
12.678 |     12.6  |   12.7
 -3.19 |     -3.1  |   -3.2
 9.999 |      9.9  |   10.0

Пример 3: Сколько событий вверх, вниз и без движения

SELECT SIGN(delta) AS direction,
       COUNT(*)    AS n
FROM events
GROUP BY SIGN(delta)
ORDER BY direction;

Результат:

direction |   n
       -1 | 210
        0 |  35
        1 | 480
Порешать SQL-задачи в тренажёре →

Типичная ошибка

TRUNC усекает в сторону нуля, поэтому для отрицательных отличается от FLOOR: TRUNC(−3.19, 1) = −3.1, а FLOOR(−3.19) = −4. В MySQL функции TRUNC нет вовсе — там TRUNCATE(x, d) с обязательным вторым аргументом. В SQLite trunc() принадлежит математическому расширению (3.35+) и принимает только один аргумент — версии со знаками после запятой нет, её эмулируют умножением и делением. SIGN(NULL) даёт NULL и в PostgreSQL сохраняет числовой тип аргумента.

Где спрашивают на собеседовании

На собесе спрашивают разницу TRUNC / FLOOR / ROUND (усечение против округления) и просят классифицировать значения на положительные, отрицательные и нулевые — тут пригодится SIGN. SIGN часто идёт в паре с CASE (метки роста/падения), TRUNC — с ROUND.

FAQ: частые вопросы про SIGN / TRUNC

Чем TRUNC отличается от FLOOR и ROUND?

TRUNC отбрасывает дробную часть в сторону нуля, ROUND округляет к ближайшему, а FLOOR всегда идёт вниз (к −∞). Для положительных чисел TRUNC и FLOOR совпадают, а для отрицательных нет: TRUNC(−2.7) = −2, FLOOR(−2.7) = −3. ROUND(−2.7) даст −3, потому что округляет по величине.

Что возвращает SIGN для нуля и NULL?

SIGN(0) возвращает 0, SIGN положительного — 1, отрицательного — −1. SIGN(NULL) возвращает NULL, поскольку знак неизвестного значения не определён. В PostgreSQL тип результата совпадает с типом аргумента (numeric остаётся numeric).

Как обстоят дела с TRUNC и SIGN в разных диалектах и SQLite?

В MySQL нет функции TRUNC — используйте TRUNCATE(x, d) с обязательными двумя аргументами. В SQLite и trunc(), и sign() относятся к математическому расширению (3.35+, флаг SQLITE_ENABLE_MATH_FUNCTIONS), причём trunc() принимает лишь один аргумент — без числа знаков после запятой. В PostgreSQL обе функции полноценные: TRUNC поддерживает второй аргумент, SIGN работает из коробки.

Задачи в тренажёре по теме

Вопросы с собеседований по теме

Смежные темы SQL

Условная логика · Агрегации

Другие функции SQL

COALESCE · NULLIF · CASE WHEN · STRING_AGG · COUNT · SUM OVER

Открыть SQL-тренажёр (565 задач) →