sqlpostgresqltruncfloor

TRUNC en SQL: descartar la parte decimal hacia cero sin redondear

Como TRUNC descarta la parte decimal hacia cero, como TRUNC(x, n) recorta a un numero de decimales y por que difiere de FLOOR en negativos.

2 min de lecturaReferencesql · postgresql · trunc · floor · rounding · mysql

TRUNC descarta la parte decimal de un numero sin redondearlo: todo lo que va despues del punto simplemente se corta. A diferencia de ROUND, la direccion es siempre la misma — hacia cero — asi que el resultado es predecible tanto para valores positivos como negativos.

Que hace TRUNC

En su forma mas simple TRUNC(x) devuelve la parte entera de un numero, descartando los decimales. No hay redondeo al mas cercano: 3.99 se convierte en 3, no en 4.

SELECT
  TRUNC(3.99)   AS a,   -- 3
  TRUNC(3.01)   AS b,   -- 3
  TRUNC(-3.99)  AS c,   -- -3
  TRUNC(2.5)    AS d;   -- 2

Propiedades clave:

  • El truncado va siempre hacia cero, no hacia abajo: -3.99 da -3, porque -3 esta mas cerca de cero que -4.
  • ROUND(2.5) daria 3, pero TRUNC(2.5) da 2: TRUNC nunca mira los digitos que descarta.
  • El tipo del resultado es numeric, asi que se conserva la precision.

TRUNC(x, n): recortar a un numero de decimales

El segundo argumento indica cuantos digitos despues del punto conservar. El resto se corta sin redondear.

SELECT
  TRUNC(123.4567, 2)  AS two_dp,    -- 123.45
  TRUNC(123.4567, 0)  AS zero_dp,   -- 123
  TRUNC(123.4567, -1) AS neg_one;   -- 120

Un n negativo trunca a la izquierda del punto: -1 pone a cero las unidades, -2 las decenas. Aplicalo a la tabla employees para agrupar salarios en cientos gruesos sin redondear hacia arriba:

SELECT
  name,
  salary,
  TRUNC(salary, -2) AS salary_bucket
FROM employees
ORDER BY salary DESC;

Un empleado que gana 4999 cae en el grupo 4900, no en 5000 — el truncado nunca empuja un valor hacia el siguiente lugar.

TRUNC frente a FLOOR en numeros negativos

Para numeros positivos TRUNC y FLOOR parecen identicos. La divergencia empieza con los negativos: FLOOR redondea hacia abajo (hacia menos infinito), mientras que TRUNC redondea hacia cero.

SELECT
  FLOOR(-3.2) AS floor_neg,  -- -4
  TRUNC(-3.2) AS trunc_neg,  -- -3
  FLOOR(3.2)  AS floor_pos,  --  3
  TRUNC(3.2)  AS trunc_pos;  --  3

Esto es facil de convertir en un bug. Supon que orders guarda reembolsos con amount negativo y quieres los "dolares enteros":

SELECT
  id,
  amount,
  FLOOR(amount) AS whole_floor,  -- -16 para -15.30
  TRUNC(amount) AS whole_trunc   -- -15 para -15.30
FROM orders
WHERE amount < 0;

Trampa: si quieres un "descartar la parte decimal" simetrico, usa TRUNC. FLOOR sobre reembolsos infla el importe cargado en un dolar entero.

Truncar dinero frente a redondear

El dinero es un campo minado propio. La contabilidad suele querer redondeo (ROUND), pero algunos calculos — comisiones, devengo de intereses, dividir un precio — exigen por ley o contrato truncar, para no "regalar" al cliente un centavo de mas.

SELECT
  u.id,
  SUM(o.amount)                         AS gross,
  ROUND(SUM(o.amount) * 0.029, 2)       AS fee_rounded,   -- redondeo
  TRUNC(SUM(o.amount) * 0.029, 2)       AS fee_truncated  -- truncado
FROM users u
JOIN orders o ON o.user_id = u.id
WHERE o.status = 'paid'
GROUP BY u.id;

Recuerda:

  • ROUND(2.575, 2) puede dar 2.58, mientras que TRUNC(2.575, 2) da siempre 2.57.
  • El truncado subestima el resultado de forma sistematica; el redondeo no. Elige con intencion.
  • Calcula sobre numeric, no sobre float: TRUNC de un float binario puede sorprenderte por el error de representacion.

MySQL: la funcion se llama TRUNCATE

MySQL no tiene la funcion TRUNC — su papel lo cumple TRUNCATE, y alli el segundo argumento es obligatorio.

-- MySQL
SELECT
  TRUNCATE(123.4567, 2) AS two_dp,   -- 123.45
  TRUNCATE(123.4567, 0) AS zero_dp;  -- 123

No la confundas con la sentencia TRUNCATE TABLE, que vacia una tabla al instante — esa es una operacion completamente distinta. ClickHouse ofrece tanto trunc(x) como truncate(x, n) como sinonimos. Recuerda una cosa: TRUNC significa "cortar hacia cero sin redondear", y el nombre de la funcion y si el segundo argumento es obligatorio dependen del motor.

Practica con ejercicios reales

Resuelve ejercicios en el entrenador de SQL con corrección instantánea y pistas.

Abrir el entrenador