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;
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 работает из коробки.