Home Functions MOD()
SQL Numeric Function

MOD()

MOD() returns the remainder of one number divided by another. MOD(a, b) is the amount left over after dividing a by b, and it is the standard way to test divisibility, tag even or odd values, and build repeating cycles.

MySQLPostgreSQLSQL ServerSQLite
Returns: The remainder left after dividing the first argument by the second. The result has the same data type family as the inputs (integer in, integer out).

Syntax

MOD(dividend, divisor)dividend % divisorMOD(a, b) OVER (...)
ParameterTypeRequiredDescription
dividend numeric yes The number being divided (the value on the left of the division).
divisor numeric yes The number to divide by. A divisor of zero raises an error or returns NULL depending on the engine.

How it works

MOD(a, b) returns the remainder of a divided by b. For example MOD(17, 5) is 2, because 5 goes into 17 three times with 2 left over. When the divisor evenly divides the dividend the remainder is 0, which is exactly what makes MOD the go-to test for divisibility.

The % operator is an equivalent shorthand in MySQL and SQL Server, so a % b means the same thing as MOD(a, b). PostgreSQL supports both MOD() and % as well. SQLite is the odd one out: it offers the % operator but does not ship a MOD() function, so on SQLite you write a % b.

Three classic uses cover most real work. Even or odd detection with MOD(n, 2) returns 0 for even numbers and 1 for odd. Sampling every Nth row uses MOD(id, n) = 0 against a sequential id. Cyclic buckets use MOD(value, k) to wrap numbers into the range 0 to k minus 1, which is handy for round robin assignment and simple hashing. See ABS() when you need to normalise the sign of a result, and CASE to turn a remainder into a readable label.

One detail worth remembering: when the dividend is negative, the sign of the remainder follows the dividend in most engines, so MOD(-7, 3) is -1 rather than 2. This matters whenever a MOD result can go negative and you were expecting a value in the range 0 to b minus 1.

Examples

Label rows even or odd with CASE

-- MOD(n, 2) is 0 for even numbers and 1 for odd
SELECT id,
       CASE WHEN MOD(id, 2) = 0 THEN 'even'
            ELSE 'odd'
       END AS parity
FROM orders
ORDER BY id;
Result
id | parity
---+-------
 1 | odd
 2 | even
 3 | odd
 4 | even

Pick every 3rd row

-- keep only ids that divide evenly by 3
SELECT id, customer
FROM orders
WHERE MOD(id, 3) = 0
ORDER BY id;
Result
id | customer
---+---------
 3 | Sara
 6 | Omar
 9 | Lina

Wrap a value into a fixed range

-- map any hour count onto a 24 hour clock (0..23)
SELECT total_hours,
       MOD(total_hours, 24) AS hour_of_day
FROM shifts;
Result
total_hours | hour_of_day
------------+------------
         10 |         10
         27 |          3
         50 |          2

The % operator is equivalent (MySQL, SQL Server)

-- a % b returns the same remainder as MOD(a, b)
SELECT MOD(17, 5) AS with_mod,
       17 % 5      AS with_operator;
Result
with_mod | with_operator
---------+--------------
       2 |            2

Assign rows to round robin buckets

-- spread ids across 3 workers: buckets 0, 1, 2
SELECT id,
       MOD(id, 3) AS worker
FROM tasks
ORDER BY id;
Result
id | worker
---+-------
 1 |      1
 2 |      2
 3 |      0
 4 |      1

Common mistakes

Wrong
-- Divisor of 0: error in some engines, NULL in others
SELECT MOD(10, 0) FROM dual;
Right
-- Guard the divisor so it is never 0
SELECT CASE WHEN divisor <> 0
            THEN MOD(10, divisor)
            ELSE NULL
       END AS safe_mod
FROM settings;

MOD by zero is not portable. MySQL and SQLite return NULL, while PostgreSQL and SQL Server raise a division by zero error. Never assume one behaviour; check the divisor first when it can be zero.

Wrong
-- Expecting 2, but negatives surprise you
SELECT MOD(-7, 3) AS r;   -- returns -1, not 2
Right
-- Force a non-negative result in the range 0..b-1
SELECT MOD(MOD(-7, 3) + 3, 3) AS r;   -- returns 2

The sign of a MOD result follows the dividend in most engines, so MOD(-7, 3) is -1. If you need a value that is always in the range 0 to b minus 1, add the divisor and take MOD again, or normalise the input with ABS().

Wrong
-- MOD() does not exist in SQLite
SELECT MOD(id, 2) FROM orders;
Right
-- Use the % operator, which SQLite does support
SELECT id % 2 FROM orders;

Do not assume both spellings work everywhere. SQLite has no MOD() function and only offers %. Conversely, older or stricter setups may reject %, so MOD() is the more portable spelling across MySQL, PostgreSQL and SQL Server.

Performance

MOD() is a cheap arithmetic operation on a single row, so the function itself is never the bottleneck. The cost comes from where you put it. A filter like WHERE MOD(id, 3) = 0 wraps the column in a function, which usually prevents the optimiser from using an index on id and forces a full scan.

If you sample rows this way on a large table often, consider storing the bucket as a computed or persisted column and indexing it, so the engine can seek the matching rows instead of computing MOD for every row. On MySQL a generated column plus an index, or on PostgreSQL an expression index such as CREATE INDEX ON orders ((id % 3)), both let the filter use an index directly.

For even or odd style splits the data is roughly half in each bucket, so an index rarely helps there anyway; a scan is expected. Reserve the index tricks for selective cases like every Nth row where the matching set is small.

Interview questions

What does MOD(a, b) return?

It returns the remainder left after dividing a by b. For example MOD(17, 5) is 2. When b divides a evenly the remainder is 0, which is why MOD is used to test divisibility.

How do you check whether a number is even or odd in SQL?

Test the remainder when dividing by 2. MOD(n, 2) = 0 means even and MOD(n, 2) = 1 means odd. You often wrap it in a CASE to produce a readable label.

SELECT n,
       CASE WHEN MOD(n, 2) = 0 THEN 'even' ELSE 'odd' END AS parity
FROM numbers;

Is the % operator the same as MOD()?

In MySQL and SQL Server, a % b is equivalent to MOD(a, b). PostgreSQL supports both spellings. SQLite has only % and does not provide a MOD() function, so the two are not interchangeable on every engine.

What happens with MOD when the dividend is negative?

In most engines the sign of the result follows the dividend, so MOD(-7, 3) returns -1 rather than 2. To always get a non-negative result in the range 0 to b minus 1, compute MOD(MOD(x, b) + b, b).

How would you select every Nth row from a table?

Use MOD against a sequential column, for example WHERE MOD(id, 10) = 0 to keep every 10th row. Be aware that wrapping the column in MOD usually disables index use, so on large tables an expression index on the MOD value can help.

Master SQL, one function at a time

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