Выборка всех дат между двумя промежутками в MySQL
Быстрый ответ
Чтобы сформировать список дат между двумя определенными значениями, вы можете воспользоваться рекурсивным CTE в MySQL следующим образом:
WITH RECURSIVE DateSeries AS (
SELECT '2023-01-01' AS target_date -- стартовая дата – Новый Год
UNION ALL
SELECT target_date + INTERVAL 1 DAY FROM DateSeries
WHERE target_date < '2023-01-10' -- указываем дату окончания
)
SELECT target_date FROM DateSeries;
Замените даты '2023-01-01'
и '2023-01-10'
на те, которые вас интересуют.
Исследуем подробнее: генерация более широкого диапазона дней
Приведенный выше пример использует рекурсивный CTE, доступный начиная с MySQL 8.0. Это удобный способ итерировать даты. Если нужен более длительный период, достаточно изменить размер интервала.
Если вы работаете с более ранней версией MySQL, воспользуйтесь числовой последовательностью или календарной таблицей. Пример запроса для такого случая:
SELECT DATE_ADD('2023-01-01', INTERVAL a.i + 10 * b.i + 100 * c.i DAY) AS Date
FROM (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) a
JOIN (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) b
JOIN (SELECT 0 i UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) c
WHERE DATE_ADD('2023-01-01', INTERVAL a.i + 10 * b.i + 100 * c.i DAY) BETWEEN '2023-01-01' AND '2023-12-31'
ORDER BY Date;
Следим за бесконечными циклами при помощи MAX_RECURSION
Рекурсивные запросы могут зациклиться, чтобы этого избежать, используйте ограничение MAX_RECURSION.
Для генерации большого количества дат удобно использовать предварительно заполненную таблицу. Это можно сравнить с песочными часами, в которых готовый песок уже есть в наличии.
Учет високосных лет и временных зон
Учет високосных лет и разных временных зон – важный момент для получения точных результатов запросов, немного похожий на жонглирование: все обязательно должно находиться в движении и в балансе.
Визуализация
Вы можете представить процесс поиска дат в диапазоне между двуми календарными точками как ловлю рыбы между двумя буями:
Буй-старт 🚩: 1 апреля
Буй-финиш 🏁: 10 апреля
Поиск дат напоминает 🎣 рыбалку:
🚩🎣🐟🐟🐟🐟🐟🐟🐟🐟🐟🐟🏁
# Каждая 🐟 обозначает одну найденную дату. Чем больше 🐟, тем богаче набор данных!
Считайте SQL вашей сетью, которой вы аккуратно собираете требуемые дни.
Индивидуализация запроса: Ваши уникальные требования
Возможности написания SQL-запросов так же многообразны, как и люди. Если вам необходимы только рабочие дни или исключить определенные праздники, вы можете настроить свой рекурсивный CTE или использовать JOIN с дополнительными таблицами для этого.
Оптимизация производительности: Эффективность – прежде всего!
Для оптимизации производительности важно предварительно сгенерировать данные и корректно их проиндексировать. Этот аспект особенно критичен при работе с большим объемом данных.
Работа с большими диапазонами дат: стратегия подзапросов и соединений
При обработке больших диапазонов дат вспомогательные подзапросы и кросс-джойны будут неоценимым инструментом. Не забудьте о правильной индексации и методах разбиения данных с целью улучшения производительности.
Полезные материалы
- MySQL :: MySQL 8.0 Справочное руководство :: 14.7 Функции даты и времени — подробно о функциях даты и времени в MySQL.
- sql – generate days from date range — обсуждение методов генерации дат в MySQL.
- MySQL – Оператор Between — разъяснение работы оператора BETWEEN в MySQL.
- Оператор SQL BETWEEN — руководство по использованию оператора SQL BETWEEN.