BETWEEN: диапазоны
BETWEEN: диапазоны
В предыдущем уроке вы освоили IN для проверки вхождения в список конкретных значений. Теперь рассмотрим смежную задачу: фильтрацию по диапазону. «Товары ценой от 1000 до 5000», «заказы за последние три месяца», «сотрудники с зарплатой от 80000 до 120000». Конечно, это можно записать через два условия с AND:
WHERE price >= 1000 AND price <= 5000
Работает корректно. Но SQL предоставляет более читабельную альтернативу — оператор BETWEEN.
Синтаксис BETWEEN
SELECT колонки
FROM таблица
WHERE колонка BETWEEN нижняя_граница AND верхняя_граница;
Эквивалент через AND:
WHERE price BETWEEN 1000 AND 5000
-- то же самое, что:
WHERE price >= 1000 AND price <= 5000
Обе границы в BETWEEN включены в диапазон. Это важная деталь — BETWEEN 1000 AND 5000 включает и 1000, и 5000.
Пример: товары в ценовом диапазоне 2000–10000 рублей:
SELECT name, price, category
FROM products
WHERE price BETWEEN 2000 AND 10000
ORDER BY price ASC;
Результат включит товары с ценой ровно 2000 и ровно 10000.
Проверь себя: что вернёт WHERE score BETWEEN 90 AND 100 для строки со score = 90?
BETWEEN с датами
BETWEEN особенно удобен для фильтрации по датам. Запрос заказов за конкретный месяц:
SELECT order_id, created_at, total_amount
FROM orders
WHERE created_at BETWEEN '2024-01-01' AND '2024-01-31'
ORDER BY created_at;
Это вернёт все заказы с 1 по 31 января 2024 года включительно.
Важный нюанс с TIMESTAMP: если колонка хранит дату и время (TIMESTAMP), то '2024-01-31' интерпретируется как '2024-01-31 00:00:00'. Заказы в 23:59 31 января не войдут в результат! Правильный способ:
WHERE created_at >= '2024-01-01'
AND created_at < '2024-02-01' -- строго меньше начала следующего месяца
Или явно с временем:
WHERE created_at BETWEEN '2024-01-01 00:00:00' AND '2024-01-31 23:59:59'
Это типичная ловушка при работе с датами и BETWEEN. При числах и датах без времени BETWEEN работает интуитивно, но с TIMESTAMP — будьте внимательны.
NOT BETWEEN: за пределами диапазона
NOT BETWEEN возвращает строки, где значение выходит за пределы диапазона:
SELECT name, price
FROM products
WHERE price NOT BETWEEN 1000 AND 5000;
Это вернёт товары дешевле 1000 рублей или дороже 5000. Эквивалент:
WHERE price < 1000 OR price > 5000
Обе границы при NOT BETWEEN тоже исключены. То есть товар с price = 1000 попадёт под price NOT BETWEEN 1000 AND 5000? Нет — он точно на границе BETWEEN, поэтому NOT BETWEEN его исключает.
Порядок границ важен
В BETWEEN нижняя граница должна быть меньше верхней. Если перепутать:
WHERE price BETWEEN 5000 AND 1000 -- вернёт 0 строк!
PostgreSQL не выдаст ошибку, но вернёт пустой результат: нет числа, которое одновременно >= 5000 и <= 1000.
Всегда пишите: BETWEEN минимум AND максимум.
BETWEEN со строками
BETWEEN работает и со строками, применяя лексикографическое сравнение:
SELECT name FROM employees WHERE name BETWEEN 'А' AND 'Д';
Это вернёт имена, лексикографически находящиеся между «А» и «Д»: Анна, Борис, Вера, Гриша, Дина, Дмитрий.
На практике строковый BETWEEN используют редко — поведение зависит от локали базы и может быть неочевидным. Лучше использовать явные условия >= 'А' AND < 'Е' или LIKE-шаблоны.
BETWEEN vs два условия AND: когда что выбрать
BETWEEN лучше, когда:
- Обе границы включены (что соответствует семантике
BETWEEN) - Диапазон числовой или датовый (без времени)
- Важна читабельность запроса
Два условия с >= и < лучше, когда:
- Нужна «полуоткрытая» граница:
>= '2024-01-01' AND < '2024-02-01' - Одна из границ динамически вычисляется
- Нужна разная логика для верхней и нижней границы
На практике оба подхода встречаются в боевом коде. Выбирайте тот, что лучше отражает смысл условия.
Практический пример: аналитика продаж
Задача: отчёт по продажам за квартал — все заказы Q1 2024 с суммой от 5000 до 100000 рублей:
SELECT order_id,
customer_id,
created_at,
total_amount
FROM orders
WHERE created_at BETWEEN '2024-01-01' AND '2024-03-31'
AND total_amount BETWEEN 5000 AND 100000
ORDER BY total_amount DESC;
Два BETWEEN условия объединены через AND. Строки попадают в результат только если удовлетворяют обоим диапазонам.
Другой пример — найти сотрудников среднего уровня зарплаты:
SELECT name, department, salary
FROM employees
WHERE salary BETWEEN 60000 AND 120000
AND department IN ('Разработка', 'QA', 'DevOps')
ORDER BY department, salary DESC;
Комбинирование BETWEEN и IN — типичный паттерн в аналитических запросах.
Типичные ошибки
1. Перепутаны границы:
WHERE age BETWEEN 30 AND 18 -- 0 строк, нужно BETWEEN 18 AND 30
2. BETWEEN с TIMESTAMP — потеря строк:
WHERE created_at BETWEEN '2024-01-01' AND '2024-01-31'
-- Не включит заказы 31 января после 00:00:00
-- Используйте: >= '2024-01-01' AND < '2024-02-01'
3. Путаница: BETWEEN включает обе границы:
-- Хотели ИСКЛЮЧИТЬ границы (открытый интервал)
WHERE price BETWEEN 100 AND 500 -- включает 100 и 500
-- Для открытого интервала: WHERE price > 100 AND price < 500
Диапазоны в разных СУБД
BETWEEN ... AND ... — стандартный SQL, работает одинаково во всех СУБД: PostgreSQL, SQLite, MySQL, SQL Server. Единственное отличие может быть в обработке граничных значений для специфических типов данных, но для чисел и стандартных дат поведение идентично.
В SQL Server есть дополнительный синтаксис для работы с датами (DATEADD, DATEDIFF), но BETWEEN работает там так же, как в PostgreSQL.
Как BETWEEN работает под капотом
Когда СУБД видит WHERE price BETWEEN 1000 AND 5000, она внутренне преобразует это в WHERE price >= 1000 AND price <= 5000. Это не упрощение — это буквальная трансформация, которую выполняет планировщик запросов перед оптимизацией.
Именно поэтому:
BETWEENподдерживает использование индексов так же, как два>=/<=условияNOT BETWEEN a AND bэквивалентноNOT (col >= a AND col <= b), что по законам де Моргана равноcol < a OR col > b- СУБД не делает разницы между этими формами при оптимизации
Знание этого эквивалента помогает понять, что BETWEEN — синтаксический сахар, а не магия.
Диапазон с одинаковыми границами
Что если BETWEEN a AND a — обе границы одинаковые?
WHERE score BETWEEN 100 AND 100
-- эквивалентно: WHERE score >= 100 AND score <= 100
-- то же самое что: WHERE score = 100
Это работает, но написать = 100 проще и понятнее. BETWEEN a AND a — формально корректно, но на практике так не пишут.
Комбинирование нескольких BETWEEN
Можно фильтровать по нескольким диапазонам одновременно:
SELECT product_id, name, price, rating
FROM products
WHERE price BETWEEN 1000 AND 15000
AND rating BETWEEN 4.0 AND 5.0;
Это вернёт товары в ценовом диапазоне 1000–15000 рублей и с рейтингом от 4.0 до 5.0. Оба условия BETWEEN объединяются через AND.
Ещё пример — отчёт о пользователях среднего возраста с определённым числом заказов:
SELECT user_id, name, age, order_count
FROM user_stats
WHERE age BETWEEN 25 AND 45
AND order_count BETWEEN 3 AND 20
ORDER BY order_count DESC;
Такие запросы типичны в аналитике: «пользователи в нужном сегменте по нескольким критериям».
BETWEEN в ON-клаузе JOIN
BETWEEN можно использовать не только в WHERE, но и в условиях соединения таблиц (ON). Это более продвинутая тема — JOIN мы подробно разберём в модуле 6. Но стоит знать, что BETWEEN не ограничен только WHERE.
Краткий итог
BETWEEN a AND b— значение в диапазоне [a, b] включительно (обе границы входят)NOT BETWEEN a AND b— значение вне диапазона (строго меньше a или строго больше b)- Нижняя граница должна быть ≤ верхней; перепутаные границы дадут 0 строк
BETWEENэквивалентен>= a AND <= b— СУБД использует их одинаково- С
TIMESTAMP-колонками осторожно:BETWEEN '2024-01-31'не включает конец дня - Для полуоткрытых интервалов (
>= a AND < b)BETWEENне подходит BETWEENработает одинаково во всех основных СУБД
Что дальше
Вы освоили диапазоны с BETWEEN. Следующая тема — одна из самых важных в SQL: специальное значение NULL и операторы IS NULL / IS NOT NULL. Понимание NULL критично для правильного написания запросов, потому что его поведение часто удивляет разработчиков из других языков программирования.