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 35BETWEEN с датами
Даты — самый частый кейс для 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 — в примерах вопросов по всем темам.