sqlpostgresqlfloorrounding

FLOOR en SQL: redondear hacia abajo al entero anterior y agrupar en buckets

Como FLOOR redondea un numero hacia abajo al entero anterior, por que los negativos se alejan de cero y en que se diferencia de TRUNC.

2 min de lecturaReferencesql · postgresql · floor · rounding · bucketing · clickhouse

FLOOR redondea un numero hacia abajo al entero mas cercano que no sea mayor que el valor original. Es el "suelo" matematico: en la recta numerica siempre te desplazas a la izquierda, hacia el entero menor.

Que hace FLOOR

La funcion toma cualquier numero y devuelve el mayor entero que sea menor o igual que el argumento. La parte decimal simplemente se descarta, pero solo para numeros no negativos.

SELECT
  FLOOR(4.9)  AS a,   -- 4
  FLOOR(4.1)  AS b,   -- 4
  FLOOR(4.0)  AS c,   -- 4
  FLOOR(-4.1) AS d;   -- -5

Propiedades clave:

  • El redondeo siempre es hacia abajo, nunca al mas cercano: 4.9 se convierte en 4, no en 5.
  • Un argumento entero no cambia: FLOOR(4.0) es 4.
  • En PostgreSQL el tipo del resultado coincide con el del argumento: numeric sigue siendo numeric, double precision sigue siendo double precision. Anade ::int si quieres un integer de verdad.

Los negativos se alejan de cero

Esta es la trampa principal. Con numeros positivos parece que FLOOR solo "corta" la parte decimal, pero con negativos redondea mas lejos de cero, porque el entero menor queda mas abajo.

SELECT
  FLOOR(2.7)  AS pos,   -- 2
  FLOOR(-2.7) AS neg;   -- -3

Compara esto con TRUNC, que siempre descarta los decimales y se mueve hacia cero:

SELECT
  TRUNC(-2.7) AS truncated,   -- -2
  FLOOR(-2.7) AS floored;     -- -3

Cuidado: si calculas rangos de edad, puntuaciones o coordenadas donde aparecen valores negativos, FLOOR y TRUNC dan resultados distintos. Usa TRUNC para "quitar los decimales"; usa FLOOR para "redondear hacia abajo en el eje".

Buckets: FLOOR(x/n)*n

El truco mas practico es agrupar valores en intervalos iguales. Para agrupar importes de pedidos en buckets de 100, divide entre 100, aplica FLOOR y multiplica de vuelta.

SELECT
  FLOOR(amount / 100) * 100 AS bucket,
  COUNT(*)                  AS orders
FROM orders
WHERE status = 'paid'
GROUP BY FLOOR(amount / 100) * 100
ORDER BY bucket;

Un pedido de 250 cae en el bucket 200 y uno de 99 en el bucket 0. El mismo truco reparte los salarios de los empleados en bandas de diez mil:

SELECT
  FLOOR(salary / 10000) * 10000 AS salary_band,
  COUNT(*)                      AS headcount
FROM employees
GROUP BY FLOOR(salary / 10000) * 10000
ORDER BY salary_band;

Cuidado: vigila la division entera. Si amount es de tipo integer, entonces amount / 100 ya queda truncado a entero antes de que FLOOR se ejecute, y los buckets se desplazan. Convierte a un tipo decimal: FLOOR(amount::numeric / 100) * 100.

La pareja con CEIL y diferencias entre motores

FLOOR siempre va de la mano de CEIL (tambien CEILING), que redondea hacia arriba. Juntos encierran un valor en un rango entero.

SELECT
  FLOOR(4.2) AS low,   -- 4
  CEIL(4.2)  AS high;  -- 5

Diferencias por dialecto:

  • PostgreSQL: FLOOR conserva el tipo numerico del argumento y los negativos se tratan con matematica estricta.
  • MySQL: FLOOR sobre DECIMAL devuelve un entero, pero para DOUBLE el resultado es tambien DOUBLE; ten cuidado al comparar tipos.
  • ClickHouse: ofrece floor(x) mas la extension floor(x, N) que redondea a N decimales, algo que el SQL estandar no tiene.

Un patron util muy comun es repartir filas de forma uniforme entre N grupos para muestreo o sharding:

SELECT
  id,
  FLOOR(RANDOM() * 4)::int AS shard   -- 0..3
FROM users;

Recuerda tres cosas: FLOOR redondea hacia abajo, los negativos se alejan de cero, y para "cortar los decimales hacia cero" necesitas TRUNC, no FLOOR.

Practica con ejercicios reales

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

Abrir el entrenador