TGViewer
SQL Ready | Базы Данных SQL Ready | Базы Данных @sql_ready · 17.5K subscribers
Post #2175 542
Почему BETWEEN может незаметно исключать данные при фильтрации по датам!

При работе с временными диапазонами часто используют BETWEEN. Но если колонка хранит дату вместе со временем, такой фильтр может возвращать не все ожидаемые записи.

Допустим, есть таблица заказов:
CREATE TABLE orders (
id BIGINT PRIMARY KEY,
created_at TIMESTAMP NOT NULL,
amount DECIMAL(12, 2)
);


Нужно получить заказы за сентябрь 2026 года. На первый взгляд подходит запрос:
SELECT *
FROM orders
WHERE created_at BETWEEN
TIMESTAMP '2026-09-01 00:00:00'
AND TIMESTAMP '2026-09-30 00:00:00';


Однако BETWEEN включает обе границы диапазона и эквивалентен сочетанию >= и <=. Поэтому запрос вернёт записи с 1 сентября по начало 30 сентября, но исключит все заказы, созданные позднее полуночи последнего дня месяца.

Например, запись со временем 2026-09-30 15:30:00 не попадёт в результат. Иногда верхнюю границу пытаются исправить вручную:
WHERE created_at BETWEEN
TIMESTAMP '2026-09-01 00:00:00'
AND TIMESTAMP '2026-09-30 23:59:59';


Но это тоже ненадёжный вариант. Если колонка поддерживает дробные доли секунды, запись 2026-09-30 23:59:59.500 окажется за пределами диапазона.

Для временных интервалов практичнее использовать полуоткрытый диапазон:
SELECT *
FROM orders
WHERE created_at >= TIMESTAMP '2026-09-01 00:00:00'
AND created_at < TIMESTAMP '2026-10-01 00:00:00';


Такой запрос включает все значения за сентябрь независимо от точности хранения времени и исключает записи следующего месяца.

Ещё одно преимущество — соседние интервалы не пересекаются. Например, при последовательной обработке данных можно использовать:
WHERE created_at >= :date_from
AND created_at < :date_to;


При условии, что следующая выборка начинается с предыдущего date_to, каждая запись на границе интервалов попадёт ровно в один диапазон.

Такой подход также хорошо сочетается с обычным B-tree индексом:
CREATE INDEX idx_orders_created_at
ON orders (created_at);


Поскольку фильтрация выполняется непосредственно по индексируемой колонке, оптимизатор может использовать диапазонное сканирование индекса. При использовании типов с часовыми поясами границы необходимо задавать в соответствии с нужной временной зоной, особенно если речь идёт о календарных днях.

🔥 Для фильтрации по временным интервалам условия >= и < обычно надёжнее, чем BETWEEN. Полуоткрытые диапазоны не зависят от точности TIMESTAMP, не пересекаются на границах и удобны для отчётности, пакетной обработки и инкрементальной загрузки данных.

➡️ SQL Ready | #практика
  • 🔥 8
  • ❤ 5
  • 👍 4
More from @sql_ready
  1. Oct 14, 2026🔴В 2025 году Россияне заработали 5,3 млрд рублей на арбитраже криптовалют По данным Минфи…
  2. Oct 14, 2026😎 SQLinfo — русскоязычный справочник по SQL! Сайт с учебными и справочными материалами по…
  3. Oct 13, 2026🖥 Oracle - ограничение количества строк и выборка Top-N! Получение первых N строк с FETCH…
  4. Oct 12, 2026Обновляйте несколько колонок одним подзапросом! Вместо нескольких одинаковых подзапросов:…
  5. Oct 9, 2026❤️ sqlite-postgres-cours — большой практический курс по базам данных! Материал ведёт от пе…
  6. Oct 8, 2026Почему UNIQUE допускает несколько NULL в PostgreSQL! Ограничение UNIQUE гарантирует уникал…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →