Ищем события за последние 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 нашел целых три строки. Подумай, почему в прошлый раз была одна строка, а в этот раз – три?

undefined
1
Задача
Модуль 4. Работа с БД, 4 уровень, 3 лекция
Недоступна
task0427
Напиши запрос, который из таблицы event выберет все поля событий, которые произошли за последние 20 дней. Дата и время событий хранится в поле date_time. Используй DATEDIFF() и CURDATE().
undefined
1
Задача
Модуль 4. Работа с БД, 4 уровень, 3 лекция
Недоступна
task0428
Напиши запрос, который из таблицы event выберет все поля событий, которые произошли за текущий месяц. Дата и время событий хранится в поле date_time. Используй YEAR(), MONTH() и CURDATE().
undefined
1
Задача
Модуль 4. Работа с БД, 4 уровень, 3 лекция
Недоступна
task0429
Напиши запрос, который из таблицы event выберет все поля событий, которые произошли за последние 2 недели. Дата и время событий хранится в поле date_time. Используй BETWEEN, DATE_SUB() и CURDATE().
undefined
1
Задача
Модуль 4. Работа с БД, 4 уровень, 3 лекция
Недоступна
task0430
Напиши запрос, который из таблицы event выберет год, месяц, день из поля date и количество событий, которые относятся к данному году, месяцу и дню. Выбрать данные только по тем дням, где больше 5 событий.
undefined
1
Задача
Модуль 4. Работа с БД, 4 уровень, 3 лекция
Недоступна
task0431
Напиши запрос, который из таблицы event выберет день недели на основе даты (date) и количество регистраций (поле type равно 'REGISTRATION'). Выбрать нужно только тот день, в котором зарегистрировались больше всего пользователей. Используй DAYNAME().
undefined
1
Задача
Модуль 4. Работа с БД, 4 уровень, 3 лекция
Недоступна
task0432
Напиши запрос, который из таблицы event выберет месяц (название) из поля date и количество событий, которые произошли в этом месяце и были неуспешными (поле status равно 'ERROR' или 'FAILED'). В выборку должны попасть только данные по самому неуспешному месяцу.
undefined
1
Задача
Модуль 4. Работа с БД, 4 уровень, 3 лекция
Недоступна
task0433
Напиши запрос, который из таблицы event выберет год, месяц, день из поля date и количество событий, которые относятся к данному году, месяцу и дню. Выбрать данные для пользователя с id = 3 (user_id), событие - решение задачи (поле type равно 'SOLVE_TASK') с успешным статусом (поле status рав