MOD и оператор % в SQL: остаток от деления

MOD(x, y) и оператор % возвращают остаток от деления x на y — это одно и то же, просто функция и оператор. Аналитику остаток нужен для сэмплирования и бакетирования: user_id % 10 разложит пользователей по 10 группам, MOD(id, 2) отделит чётные от нечётных, остаток помогает брать «каждую N-ю строку». В PostgreSQL и MySQL есть и MOD(), и %; в SQLite оператор % работает всегда, но функция mod() — только в математическом расширении (3.35+), и оператор % там работает лишь с целыми.

Синтаксис

MOD(dividend, divisor) dividend % divisor

Примеры использования

Пример 1: Разложить пользователей по 10 бакетам

SELECT user_id,
       MOD(user_id, 10) AS bucket
FROM users
LIMIT 3;

Результат:

user_id | bucket
   101  |     1
   105  |     5
   110  |     0

Пример 2: Распределение заказов по остатку от 3

SELECT MOD(order_id, 3) AS grp,
       COUNT(*) AS cnt
FROM orders
GROUP BY MOD(order_id, 3)
ORDER BY grp;

Результат:

grp | cnt
  0 | 412
  1 | 405
  2 | 400
Порешать SQL-задачи в тренажёре →

Типичная ошибка

Знак результата наследует делимое (стандарт SQL, PostgreSQL, MySQL): MOD(−7, 3) = −1, а не 2. Деление на ноль ведёт себя по-разному: PostgreSQL выбрасывает ошибку, а MySQL и SQLite возвращают NULL. В SQLite оператор % приводит оба операнда к целым (дробного остатка не будет) — для чисел с плавающей точкой берите mod() из математического расширения. Приоритет % такой же, как у * и /.

Где спрашивают на собеседовании

Классика собеса — «разбейте пользователей на A/B-группы» или «выберите каждую N-ю запись»: ответ через остаток. Идёт в паре с FLOOR (бины) и хешированием id для детерминированного сэмплинга.

FAQ: частые вопросы про MOD / %

MOD и % — это одно и то же?

Да, MOD(x, y) и x % y вычисляют один и тот же остаток от деления; % — это инфиксный оператор, MOD — функциональная запись. В PostgreSQL и MySQL доступны обе формы, выбор чисто стилистический. В SQLite надёжнее оператор %, потому что функция mod() требует математической сборки.

Какой знак у остатка для отрицательных чисел?

В PostgreSQL, MySQL и по стандарту SQL знак результата совпадает со знаком делимого: MOD(−7, 3) = −1, а MOD(7, −3) = 1. Это не математический «неотрицательный» остаток, поэтому для гарантированно положительного результата пишут ((x % n) + n) % n. Особенно важно при бакетировании по id, где встречаются отрицательные значения.

Есть ли MOD в SQLite?

Оператор % в SQLite есть всегда, но он работает только с целыми — оба операнда приводятся к integer. Отдельная функция mod() появилась лишь в математическом расширении SQLite 3.35 (флаг SQLITE_ENABLE_MATH_FUNCTIONS) и поддерживает дробные числа. Деление или остаток на ноль в SQLite дают NULL, а не ошибку.

Задачи в тренажёре по теме

Вопросы с собеседований по теме

Смежные темы SQL

Агрегации · Условная логика

Другие функции SQL

COALESCE · NULLIF · CASE WHEN · STRING_AGG · COUNT · SUM OVER

Открыть SQL-тренажёр (565 задач) →