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,
FLOOR(4.1) AS b,
FLOOR(4.0) AS c,
FLOOR(-4.1) AS d;
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,
FLOOR(-2.7) AS neg;
Compara esto con TRUNC, que siempre descarta los decimales y se mueve hacia cero:
SELECT
TRUNC(-2.7) AS truncated,
FLOOR(-2.7) AS floored;
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,
CEIL(4.2) AS high;
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
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.
FLOORredondea 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; -- -5Propiedades clave:
4.9se convierte en4, no en5.FLOOR(4.0)es4.numericsigue siendonumeric,double precisionsigue siendodouble precision. Anade::intsi quieres unintegerde verdad.Los negativos se alejan de cero
Esta es la trampa principal. Con numeros positivos parece que
FLOORsolo "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; -- -3Compara 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; -- -3Buckets: 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
FLOORy 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
250cae en el bucket200y uno de99en el bucket0. 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;La pareja con CEIL y diferencias entre motores
FLOORsiempre va de la mano deCEIL(tambienCEILING), que redondea hacia arriba. Juntos encierran un valor en un rango entero.SELECT FLOOR(4.2) AS low, -- 4 CEIL(4.2) AS high; -- 5Diferencias por dialecto:
FLOORconserva el tipo numerico del argumento y los negativos se tratan con matematica estricta.FLOORsobreDECIMALdevuelve un entero, pero paraDOUBLEel resultado es tambienDOUBLE; ten cuidado al comparar tipos.floor(x)mas la extensionfloor(x, N)que redondea aNdecimales, 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:
FLOORredondea hacia abajo, los negativos se alejan de cero, y para "cortar los decimales hacia cero" necesitasTRUNC, noFLOOR.