🙏 Помогите проекту не остановиться. В прошлом месяце мы собрали всего $32 — этого хватает только на серверы. Без вашей поддержки новых уроков и функций не будет. Поддержать сейчас →
SQL код скопирован в буфер обмена
EN PT FR

Урок 3.4 · Время чтения: ~9 мин

Функции работы с датой и временем в SQL позволяют извлекать, изменять и форматировать значения дат и времени. Эти функции широко используются для анализа временных данных, фильтрации по дате, вычисления интервалов и форматирования вывода. В этом уроке рассмотрены наиболее часто используемые функции с примерами на базе данных Sakila.

Основные функции даты и времени в SQL

Важно: CURRENT_DATE, CURRENT_TIME, CURRENT_TIMESTAMP во многих СУБД относятся к специальным SQL-выражениям (или алиасам соответствующих функций), а не к "обычным" функциям вида NAME(arg1, arg2, ...). Из-за этого синтаксис и детали поведения могут отличаться между СУБД.

Общие функции даты и времени

CURRENT_DATE - Специальное выражение, возвращающее текущую дату (без времени).

Синтаксис:

CURRENT_DATE

Пример:

SELECT CURRENT_DATE AS today;

Результат: Текущая дата, например: 2025-06-03

CURRENT_TIME - Специальное выражение/алиас, возвращающее текущее время (без даты).

Синтаксис:

CURRENT_TIME
CURRENT_TIME()
CURRENT_TIME(precision)

Пример:

SELECT CURRENT_TIME AS now_time;

Результат: Текущее время. С указанием точности (например, CURRENT_TIME(3)) возвращается время с долями секунды.

CURRENT_TIMESTAMP / NOW() - Возвращает текущие дату и время (часто как специальное выражение/алиас).

Синтаксис:

CURRENT_TIMESTAMP
CURRENT_TIMESTAMP()
CURRENT_TIMESTAMP(precision)
NOW()

Пример:

SELECT CURRENT_TIMESTAMP AS now_datetime;
SELECT NOW() AS now_datetime;

Результат: Текущие дата и время, например: 2025-06-03 14:25:30

Важно: в большинстве СУБД CURRENT_DATE/CURRENT_TIME/CURRENT_TIMESTAMP фиксируются на момент начала выполнения запроса (а в некоторых режимах - на момент начала транзакции). Поэтому в рамках одного запроса все строки обычно получают одно и то же значение.

Если нужна "текущая метка времени" именно в момент вычисления для конкретной строки, используют другие функции, зависящие от СУБД (например, SYSDATE() в MySQL/MariaDB, clock_timestamp() в PostgreSQL).

DATE() - Извлекает только дату из значения даты и времени.

Синтаксис:

DATE(datetime_value)

Пример:

SELECT DATE(rental_date) AS rental_only_date
FROM rental
LIMIT 3;

Результат: Возвращает только дату из столбца rental_date.

TIME() - Извлекает только время из значения даты и времени.

Синтаксис:

TIME(datetime_value)

Пример:

SELECT TIME(rental_date) AS rental_only_time
FROM rental
LIMIT 3;

Результат: Возвращает только время из столбца rental_date.

YEAR() - Извлекает год из значения даты.

Синтаксис:

YEAR(date_value)

Пример:

SELECT YEAR(rental_date) AS rental_year
FROM rental
LIMIT 3;

Результат: Возвращает год из даты аренды.

MONTH() - Извлекает месяц из значения даты.

Синтаксис:

MONTH(date_value)

Пример:

SELECT MONTH(rental_date) AS rental_month
FROM rental
LIMIT 3;

Результат: Возвращает месяц из даты аренды.

DAY() - Извлекает день месяца из значения даты.

Синтаксис:

DAY(date_value)

Пример:

SELECT DAY(rental_date) AS rental_day
FROM rental
LIMIT 3;

Результат: Возвращает день месяца из даты аренды.

WEEK() - Возвращает номер недели для даты (MySQL/MariaDB).

Синтаксис:

WEEK(date_value)
WEEK(date_value, mode)

Пример:

SELECT rental_id, rental_date, WEEK(rental_date) AS rental_week
FROM rental
LIMIT 5;

Результат: Возвращает номер недели для каждой даты аренды.

WEEK() часто используют в WHERE и GROUP BY, когда нужно строить недельные отчеты. Важно учитывать параметр mode: он влияет на то, какой день считается началом недели и как определяется первая неделя года.

DATE_ADD() - Добавляет указанный интервал к дате.

Синтаксис:

DATE_ADD(date, INTERVAL value unit)

Пример:

SELECT DATE_ADD(rental_date, INTERVAL 7 DAY) AS return_due
FROM rental
LIMIT 3;

Результат: Возвращает дату, увеличенную на 7 дней.

DATE_SUB() - Вычитает указанный интервал из даты.

Синтаксис:

DATE_SUB(date, INTERVAL value unit)

Пример:

SELECT DATE_SUB(rental_date, INTERVAL 3 DAY) AS three_days_before
FROM rental
LIMIT 3;

Результат: Возвращает дату, уменьшенную на 3 дня.

DATEDIFF() - Возвращает количество дней между двумя датами.

Синтаксис:

DATEDIFF(date1, date2)

Пример:

SELECT DATEDIFF(return_date, rental_date) AS rental_duration
FROM rental
WHERE return_date IS NOT NULL
LIMIT 3;

Результат: Количество дней между датой возврата и датой аренды.

DATE_FORMAT() - Форматирует дату в заданном формате (MySQL).

Синтаксис:

DATE_FORMAT(date, format)

Пример:

SELECT DATE_FORMAT(rental_date, '%d.%m.%Y') AS formatted_date
FROM rental
LIMIT 3;

Результат: Дата в формате дд.мм.гггг, например: 03.06.2025

Общие спецификаторы формата:

  • %Y: Год (4 цифры)
  • %m: Месяц (2 цифры)
  • %d: День месяца (2 цифры)
  • %H: Час (24-часовой формат)
  • %i: Минуты
  • %s: Секунды

STRFTIME() - Форматирует дату/время (SQLite, PostgreSQL).

Синтаксис:

STRFTIME(format, date)

Пример:

SELECT STRFTIME('%Y-%m-%d', rental_date) AS formatted_date
FROM rental
LIMIT 3;

Результат: Дата в формате гггг-мм-дд.

TIMESTAMPDIFF() - Разница между двумя датами/временем в заданных единицах (MySQL).

Синтаксис:

TIMESTAMPDIFF(unit, datetime1, datetime2)

Пример:

SELECT TIMESTAMPDIFF(DAY, rental_date, return_date) AS days_rented
FROM rental
WHERE return_date IS NOT NULL
LIMIT 3;

Результат: Количество дней между датой аренды и возврата.

EXTRACT() - Извлекает часть даты или времени (год, месяц, день и т.д.).

Синтаксис:

EXTRACT(part FROM date)

Пример:

SELECT EXTRACT(YEAR FROM rental_date) AS rental_year
FROM rental
LIMIT 3;

Результат: Извлекает год из даты аренды.


Практическое применение

  1. Нахождение фильмов, арендованных за последние 30 дней:
    SELECT *
    FROM rental
    WHERE rental_date > DATE_SUB(CURRENT_DATE, INTERVAL 30 DAY);
    
  2. Подсчет количества аренд в каждом месяце:
    SELECT YEAR(rental_date) AS year, MONTH(rental_date) AS month, COUNT(*) AS rentals
    FROM rental
    GROUP BY year, month
    ORDER BY year DESC, month DESC;
    
  3. Форматирование даты аренды для отчета:
    SELECT DATE_FORMAT(rental_date, '%d.%m.%Y') AS formatted_rental
    FROM rental
    LIMIT 5;
    
  4. Группировка аренд по неделям:
    SELECT YEAR(rental_date) AS year, WEEK(rental_date, 1) AS week_num, COUNT(*) AS rentals
    FROM rental
    GROUP BY year, week_num
    ORDER BY year DESC, week_num DESC;
    

Часто задаваемые вопросы

Когда использовать DATEDIFF(), а когда TIMESTAMPDIFF()?

DATEDIFF() возвращает разницу только в днях между двумя датами. TIMESTAMPDIFF() гибче: можно считать разницу в секундах, минутах, часах, днях, месяцах и других единицах.

Чем DATE() отличается от DATE_FORMAT()?

DATE() просто отбрасывает время и возвращает дату. DATE_FORMAT() формирует строковое представление даты в нужном формате, например '%d.%m.%Y'.

Зачем нужен второй аргумент в WEEK(date, mode)?

Параметр mode задает правила расчета номера недели: первый день недели и логику определения первой недели года. Это важно для единообразной отчетности.

Почему функции с датой могут работать по-разному в разных СУБД?

Разные СУБД могут по-разному трактовать синтаксис, таймзоны, форматы и календарные правила. Поэтому для кросс-СУБД запросов нужно проверять документацию конкретного движка.


Вопросы для собеседования

Как вы объясните разницу между CURRENT_DATE и CURRENT_TIMESTAMP?

CURRENT_DATE возвращает только текущую дату, без времени. CURRENT_TIMESTAMP возвращает и дату, и время, поэтому его используют, когда важна точная временная метка.

Когда вы выберете WEEK() вместо группировки по дням или месяцам?

WEEK() полезен для недельной аналитики: сравнения динамики продаж, аренд или заказов по неделям. Это компромисс между слишком детальным дневным и слишком грубым месячным уровнем.

Какие риски у фильтрации по функции в WHERE, например DATE(rental_date) = ...?

Такой фильтр может мешать использованию индекса по исходному столбцу и ухудшать производительность. Часто лучше фильтровать диапазоном (>= и <) без оборачивания столбца функцией.

Как сделать форматирование даты переносимым между СУБД?

Нужно учитывать, что форматирующие функции отличаются (DATE_FORMAT, TO_CHAR, STRFTIME). Для переносимости обычно выносят форматирование в слой приложения или используют СУБД-специфичные версии запросов.


Ключевые выводы этого урока:

  • Функции даты и времени помогают фильтровать, агрегировать и форматировать временные данные прямо в SQL.
  • CURRENT_DATE, CURRENT_TIME и CURRENT_TIMESTAMP часто являются специальными выражениями, а их поведение зависит от СУБД.
  • DATE_ADD, DATE_SUB, DATEDIFF и TIMESTAMPDIFF решают задачи работы с интервалами.
  • WEEK() удобен для недельной аналитики, но важно явно выбрать mode.
  • Для кросс-СУБД запросов нужно учитывать различия синтаксиса и календарной логики.

В следующем уроке мы разберем строковые функции SQL и научимся обрабатывать текстовые данные в запросах.

Урок 3.5: Основные строковые функции в SQL

Попробуйте решить следующие задачи, чтобы закрепить материал этого урока.

  1. Лучший месяц по сумме платежей
  2. Анализ данных о прокате фильма
  3. Подсчитать количество выходных дней в месяце
  4. Среднее время активности клиента
  5. Распределение клиентов по дням недели