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,
TRUNC(3.01) AS b,
TRUNC(-3.99) AS c,
TRUNC(2.5) AS d;
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,
TRUNC(123.4567, 0) AS zero_dp,
TRUNC(123.4567, -1) AS neg_one;
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,
TRUNC(-3.2) AS trunc_neg,
FLOOR(3.2) AS floor_pos,
TRUNC(3.2) AS trunc_pos;
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,
TRUNC(amount) AS whole_trunc
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,
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;
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.
SELECT
TRUNCATE(123.4567, 2) AS two_dp,
TRUNCATE(123.4567, 0) AS zero_dp;
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.
TRUNCdescarta la parte decimal de un numero sin redondearlo: todo lo que va despues del punto simplemente se corta. A diferencia deROUND, 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.99se convierte en3, no en4.SELECT TRUNC(3.99) AS a, -- 3 TRUNC(3.01) AS b, -- 3 TRUNC(-3.99) AS c, -- -3 TRUNC(2.5) AS d; -- 2Propiedades clave:
-3.99da-3, porque-3esta mas cerca de cero que-4.ROUND(2.5)daria3, peroTRUNC(2.5)da2: TRUNC nunca mira los digitos que descarta.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; -- 120Un
nnegativo trunca a la izquierda del punto:-1pone a cero las unidades,-2las decenas. Aplicalo a la tablaemployeespara 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
4999cae en el grupo4900, no en5000— el truncado nunca empuja un valor hacia el siguiente lugar.TRUNC frente a FLOOR en numeros negativos
Para numeros positivos
TRUNCyFLOORparecen identicos. La divergencia empieza con los negativos:FLOORredondea hacia abajo (hacia menos infinito), mientras queTRUNCredondea 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; -- 3Esto es facil de convertir en un bug. Supon que
ordersguarda reembolsos conamountnegativo 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.FLOORsobre 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 dar2.58, mientras queTRUNC(2.575, 2)da siempre2.57.numeric, no sobrefloat:TRUNCde unfloatbinario puede sorprenderte por el error de representacion.MySQL: la funcion se llama TRUNCATE
MySQL no tiene la funcion
TRUNC— su papel lo cumpleTRUNCATE, 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; -- 123No la confundas con la sentencia
TRUNCATE TABLE, que vacia una tabla al instante — esa es una operacion completamente distinta. ClickHouse ofrece tantotrunc(x)comotruncate(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.