Ищем события за последние 30 дней

Еще одна часто возникающая задача – это поиск строк, которые относятся к определенному диапазону дат. В принципе в этом нет ничего сложного, если начальная и конечная даты диапазона фиксированы: SQL умеет сравнивать даты так же хорошо, как и числа.

К датам можно применять операторы сравнения: <, >, <= и т. п. Кроме того, есть специальный оператор BETWEEN, который тоже умеет работать с датами. Давай для примера напишем запрос, который отберет все задачи из таблицы task, которые нужно сделать летом 2022 года. Запрос будет выглядеть так:

SELECT * FROM task  
WHERE task.deadline BETWEEN '2022-06-01' AND '2022-08-31'

Результат этого запроса будет таким:

id emploee_id name deadline
1 1 Исправить багу на фронтенде 2022-06-01
2 2 Исправить багу на бэкенде 2022-06-15
3 5 Купить кофе 2022-07-01
4 5 Купить кофе 2022-08-01

Но что писать в запросе, если мы хотим получить задачи, например, за последние 30 дней. Где последние 30 дней прямо привязаны ко времени выполнения запроса. То есть если запрос выполняется 25 июля, то нужно выбрать даты с 25 июня по 24 июля. Как привязать интервал дат к текущему времени?

Для этого нужно воспользоваться функцией сложения дат:

DATE_ADD (дата, INTERVAL выражение единицы)

Думаю, легче будет объяснить с помощью нескольких примеров:

# Запрос Результат
1 DATE_ADD('2022-06-04', INTERVAL 5 DAY) 2022-06-09
2 DATE_ADD('2022-06-04', INTERVAL 4 WEEK) 2022-07-02
3 DATE_ADD('2022-06-04', INTERVAL 2 MONTH) 2022-08-04
4
5 DATE_SUB('2022-06-04', INTERVAL 5 DAY) 2022-05-30
6 DATE_SUB('2022-06-04', INTERVAL 4 WEEK) 2022-05-07
7 DATE_SUB('2022-06-04', INTERVAL 2 MONTH) 2022-04-04

Кстати, из определенной даты можно так же вычитать определенное количество дней, недель, месяцев и лет.

И если вернуться к нашему запросу – получить данные за последние 30 дней, то нам нужны две даты этого диапазона:

  • CURDATE() – конец диапазона
  • DATE_SUB( CURDATE() , INTERVAL 30 DAY) – начало диапазона

Запрос будет выглядеть так:

SELECT * FROM task WHERE task.deadline  
BETWEEN DATE_SUB( CURDATE() , INTERVAL 30 DAY) AND CURDATE() 

Результат этого запроса будет таким (у меня сегодня 4 июня 2022 года):

id emploee_id name deadline
1 1 Исправить багу на фронтенде 2022-06-01

Как найти разницу между двумя датами

И еще одна полезная функция. Иногда может понадобиться вычислить разницу между двумя датами в днях. Для этого у SQL есть специальная функция – DATEDIFF().

Работать с ней очень просто:

DATEDIFF (дата1, дата2)

Из первой даты просто вычитается вторая. Если дата2 идет после дата1, то результат будет отрицательным.

Кстати, мы можем переписать наш предыдущий запрос, используя функцию DATEDIFF(). Нам нужно отобрать все задачи из таблицы task, дедлайн которых отличается от текущей даты не более чем на 30 дней. Вот как будет выглядеть этот запрос:

SELECT * FROM task WHERE DATEDIFF(task.deadline, CURDATE() ) < 30 AND DATEDIFF(task.deadline, CURDATE() ) > -30

Результат этого запроса будет таким (у меня сегодня 4 июня 2022 года):

id emploee_id name deadline
1 1 Исправить багу на фронтенде 2022-06-01
2 2 Исправить багу на бэкенде 2022-06-15
3 5 Купить кофе 2022-07-01

В этот раз SQL нашел целых три строки. Подумай, почему в прошлый раз была одна строка, а в этот раз – три?