BETWEEN в SQL — фильтрация по диапазону

Коротко

BETWEEN — оператор WHERE, который проверяет, попадает ли значение в диапазон. Вместо amount >= 1000 AND amount <= 5000 пишете amount BETWEEN 1000 AND 5000 — короче и читаемее. BETWEEN включает обе границы, работает с числами, датами и строками. На собеседовании по SQL BETWEEN спрашивают не столько ради синтаксиса, сколько ради подводных камней — особенно с датами.

Синтаксис

SELECT *
FROM table_name
WHERE column BETWEEN low AND high

Это эквивалентно:

WHERE column >= low AND column <= high

Обе границы включены — low и high попадают в результат. Если перепутать порядок (BETWEEN 5000 AND 1000), результат будет пустым — нижняя граница всегда идёт первой.

BETWEEN включает обе границы

Это самый частый вопрос на собеседовании про BETWEEN: включает ли он границы? Да, обе. BETWEEN — это >= плюс <=, а не > и <.

SELECT *
FROM products
WHERE price BETWEEN 100 AND 500

Товар с ценой 100 попадёт в результат. Товар с ценой 500 — тоже.

BETWEEN с числами

Типичный сценарий — фильтрация по диапазону суммы, возрасту или рейтингу:

-- заказы от 1000 до 5000 рублей
SELECT order_id, user_id, amount
FROM orders
WHERE amount BETWEEN 1000 AND 5000

-- пользователи 25-35 лет
SELECT user_id, name, age
FROM users
WHERE age BETWEEN 25 AND 35

BETWEEN с датами

Даты — самый частый кейс для BETWEEN в аналитике. Фильтрация за январь 2026:

SELECT *
FROM events
WHERE event_date BETWEEN '2026-01-01' AND '2026-01-31'

Если event_date имеет тип DATE — всё работает корректно. Но если колонка хранит TIMESTAMP, начинаются проблемы.

Подводный камень: BETWEEN с timestamp

Это главная ловушка BETWEEN, которую спрашивают на собеседованиях. Допустим, created_at — это TIMESTAMP:

-- ПРОБЛЕМА: теряем данные 31 января
SELECT *
FROM orders
WHERE created_at BETWEEN '2026-01-01' AND '2026-01-31'

Почему? '2026-01-31' превращается в '2026-01-31 00:00:00'. Все заказы 31 января после полуночи (например, 2026-01-31 14:30:00) не попадут в выборку. Вы потеряете почти весь последний день.

Правильный подход — использовать >= и < вместо BETWEEN:

-- ПРАВИЛЬНО: все данные за январь
SELECT *
FROM orders
WHERE created_at >= '2026-01-01'
  AND created_at < '2026-02-01'

Подробнее о работе с датами — в гайде по датам в SQL.

NOT BETWEEN

NOT BETWEEN исключает диапазон — возвращает строки, где значение меньше нижней границы или больше верхней:

-- заказы дешевле 1000 или дороже 5000
SELECT *
FROM orders
WHERE amount NOT BETWEEN 1000 AND 5000

Эквивалентно amount < 1000 OR amount > 5000. Границы 1000 и 5000 не попадают в результат.

BETWEEN vs >= AND <=

По сути — одно и то же. Оптимизатор разворачивает BETWEEN в >= и <=, разницы в производительности нет. Выбирайте по читаемости:

  • BETWEEN — удобнее для простых диапазонов: age BETWEEN 18 AND 65
  • >= AND < — обязательно для дат с TIMESTAMP, чтобы правильно задать полуоткрытый интервал

Некоторые команды используют только >= / <= везде для единообразия — это тоже нормально.

Практические примеры

Выручка за квартал:

SELECT DATE_TRUNC('month', order_date) AS month,
       SUM(amount) AS revenue
FROM orders
WHERE order_date BETWEEN '2026-01-01' AND '2026-03-31'
GROUP BY 1
ORDER BY 1

Пользователи с умеренной активностью:

SELECT user_id, session_count
FROM user_stats
WHERE session_count BETWEEN 5 AND 20

Заказы вне рабочих часов (NOT BETWEEN):

SELECT order_id, created_at
FROM orders
WHERE EXTRACT(HOUR FROM created_at) NOT BETWEEN 9 AND 18

Типичные ошибки

BETWEEN с TIMESTAMP теряет последний день. WHERE created_at BETWEEN '2026-01-01' AND '2026-01-31' превращает '2026-01-31' в полночь — данные за 31 января после 00:00:00 пропадают. Используйте >= AND < с первым днём следующего периода.

Перевёрнутые границы. WHERE age BETWEEN 35 AND 25 вернёт 0 строк. Нижняя граница всегда первая: BETWEEN 25 AND 35.

BETWEEN с NULL. Если значение в колонке — NULL, то NULL BETWEEN 1 AND 10 вернёт NULL, а не FALSE. Строка не попадёт в результат. Если нужно учитывать NULL — добавляйте OR column IS NULL.

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

-- Включает ли BETWEEN обе границы? -- Да. BETWEEN 1 AND 10 — это >= 1 AND <= 10. И 1, и 10 попадают в результат.

-- Чем опасен BETWEEN при фильтрации по TIMESTAMP? -- BETWEEN '2026-01-01' AND '2026-01-31' превращает правую границу в '2026-01-31 00:00:00' и теряет данные после полуночи 31-го числа. Для TIMESTAMP используйте >= AND <.

-- **Чем BETWEEN отличается от >= AND <=?** -- Ничем по результату — BETWEEN это синтаксический сахар для >= AND <=. Оптимизатор обрабатывает их одинаково.

-- Что вернёт WHERE amount BETWEEN 5000 AND 1000? -- Пустой результат. BETWEEN требует, чтобы первое значение было меньше или равно второму. Перевёрнутые границы — это amount >= 5000 AND amount <= 1000, что невозможно.

-- Напишите запрос: пользователи 25-35 лет с доходом от 50 000 до 150 000. -- SELECT * FROM users WHERE age BETWEEN 25 AND 35 AND income BETWEEN 50000 AND 150000.

Потренируйтесь в тренажёре

BETWEEN — простой оператор, но ловушка с TIMESTAMP стоит каждому собеседованию. Потренируйтесь на реальных задачах — откройте тренажёр с 200+ задачами по SQL и разборами.

FAQ

BETWEEN работает со строками?

Да. WHERE name BETWEEN 'А' AND 'М' вернёт имена, начинающиеся на буквы от А до М (лексикографическое сравнение). На практике со строками используется редко — результат зависит от кодировки и регистра.

Можно ли использовать BETWEEN с подзапросом?

Да. WHERE amount BETWEEN (SELECT MIN(amount) FROM orders) AND (SELECT MAX(amount) FROM orders) — корректный синтаксис. Но читаемость страдает, и чаще такие задачи решают иначе.

BETWEEN работает с дробными числами?

Да. WHERE rating BETWEEN 4.0 AND 5.0 включает 4.0, 5.0 и все значения между ними — 4.1, 4.5, 4.99 и т.д. Тип данных (INTEGER, NUMERIC, FLOAT) не влияет на логику.

Больше материалов

Разобрали BETWEEN — двигайтесь дальше. В тренажёре Карьерник задачи на фильтрацию, джойны и агрегации с разборами. Больше вопросов по SQL — в примерах вопросов по всем темам.