Home Functions FLOOR()
SQL Numeric Function

FLOOR()

FLOOR() rounds a number DOWN to the nearest integer, always toward negative infinity, so FLOOR(2.9) is 2 and FLOOR(-1.2) is -2.

MySQLPostgreSQLSQL ServerSQLite
Returns: The largest integer value that is less than or equal to the input. The value returned keeps the numeric type of the argument (an integer-valued number), not a rounded-to-string result.

Syntax

FLOOR(number)FLOOR(column)FLOOR(expression)
ParameterTypeRequiredDescription
number numeric yes Any numeric value or expression. FLOOR returns the greatest integer that is not greater than this value.

How it works

FLOOR() takes a number and returns the largest whole number that is less than or equal to it. It always rounds down: FLOOR(2.1), FLOOR(2.5) and FLOOR(2.9) all return 2. It is the mirror image of CEIL(), which rounds up.

The important detail is what "down" means for negative numbers. FLOOR rounds toward negative infinity, not toward zero. So FLOOR(-1.2) is -2, because -2 is the largest integer that is still less than or equal to -1.2. This is different from truncation, which simply drops the fractional part and moves toward zero. See TRUNCATE() for that behaviour.

A very common use of FLOOR() is bucketing continuous values into fixed ranges. Dividing, flooring and multiplying back, as in FLOOR(age / 10) * 10, snaps every value down to the start of its band, which groups ages into decades, prices into brackets, and timestamps into intervals. It is available in every major dialect: MySQL, PostgreSQL, SQL Server and SQLite. For rounding to the nearest integer rather than always down, use CEIL() or the standard ROUND function.

Examples

Round a value down to whole units

-- 4 boxes hold 10 items each; how many full boxes?
SELECT FLOOR(47 / 10.0) AS full_boxes;
Result
full_boxes
----------
         4

Bucket ages into decades

-- snap every age down to the start of its decade
SELECT name, age,
       FLOOR(age / 10) * 10 AS age_band
FROM customers
ORDER BY age;
Result
name  | age | age_band
------+-----+---------
 Sara |  19 |      10
 Omar |  27 |      20
 Lina |  34 |      30
 Ali  |  41 |      40

FLOOR with a negative number

-- FLOOR rounds toward negative infinity, not toward zero
SELECT FLOOR(-1.2) AS a,
       FLOOR(-0.1) AS b,
       FLOOR( 2.9) AS c;
Result
  a |  b | c
----+----+---
 -2 | -1 | 2

FLOOR versus casting to an integer

-- CAST truncates toward zero; FLOOR rounds down.
-- They disagree on negative values.
SELECT FLOOR(-3.7)          AS floor_val,
       CAST(-3.7 AS INT)    AS cast_val;
Result
floor_val | cast_val
----------+---------
       -4 |       -3

Common mistakes

Wrong
-- Expecting FLOOR to drop the fraction (truncate).
-- For -1.9 this returns -2, not -1.
SELECT FLOOR(-1.9);   -- -2
Right
-- Use TRUNCATE (or CAST to int) to move toward zero
SELECT TRUNCATE(-1.9, 0);   -- -1

The most common FLOOR() mistake: assuming it truncates toward zero. FLOOR always rounds toward negative infinity, so FLOOR(-1.9) is -2. If you want to just drop the decimals, use TRUNCATE() instead.

Wrong
-- Using FLOOR when you meant "nearest"
-- FLOOR(2.8) is 2, losing the near round-up
SELECT FLOOR(2.8) AS score;   -- 2
Right
-- ROUND goes to the nearest integer
SELECT ROUND(2.8) AS score;   -- 3

Do not confuse FLOOR with ROUND. FLOOR always goes down, so FLOOR(2.8) is 2. ROUND returns the nearest integer, so ROUND(2.8) is 3. Pick FLOOR only when you specifically want the value rounded down.

Performance

FLOOR() is a cheap scalar operation applied per row, so it has almost no cost on its own. The performance trap is wrapping an indexed column in FLOOR() inside a WHERE clause, as in WHERE FLOOR(price) = 10. That makes the predicate non-sargable: the database must compute FLOOR for every row and cannot use an index on price.

When you need to filter on a floored value, rewrite the condition as a range on the raw column, for example WHERE price >= 10 AND price < 11, which lets the optimiser use an index range scan. Reserve FLOOR for the SELECT list and for GROUP BY bucketing, where it runs once per output row rather than blocking an index.

Interview questions

What does FLOOR() do, and how is it different from CEIL()?

FLOOR() returns the largest integer less than or equal to the input, so it always rounds down. CEIL() returns the smallest integer greater than or equal to the input, so it always rounds up. For example FLOOR(2.4) is 2 while CEIL(2.4) is 3.

What is FLOOR(-1.2), and why?

It is -2. FLOOR rounds toward negative infinity, and -2 is the largest integer that is still less than or equal to -1.2. It does not round toward zero, so it is not -1.

How is FLOOR different from truncating or casting to an integer?

Truncation (and a plain CAST to int) drops the fractional part and moves toward zero, so both give -3 for -3.7. FLOOR moves toward negative infinity, giving -4 for -3.7. They agree on positive numbers but differ on negatives. Use TRUNCATE() when you want the toward-zero behaviour.

SELECT FLOOR(-3.7)       AS floor_val,
       TRUNCATE(-3.7, 0) AS trunc_val;

How would you group a continuous column into fixed-size buckets?

Divide by the bucket size, floor the result, then multiply back. For decades that is FLOOR(age / 10) * 10, which snaps each value down to the start of its band. The same pattern works for price brackets and time intervals.

SELECT FLOOR(age / 10) * 10 AS age_band,
       COUNT(*)             AS customers
FROM customers
GROUP BY FLOOR(age / 10) * 10
ORDER BY age_band;

Why can wrapping a column in FLOOR() slow down a query?

A predicate like WHERE FLOOR(price) = 10 is non-sargable: the database must compute FLOOR for every row and cannot use an index on price. Rewrite it as a range such as price >= 10 AND price < 11 so an index range scan can be used.

Master SQL, one function at a time

Browse the full SQL functions library, or learn the fundamentals with our free, structured courses.