0Pricing
Coding Interview Prep · Урок

Арифметика дат и интервалы

Сложение и вычитание периодов, а также вычисление разницы между датами

«Арифметика дат и интервалы» — бесплатный урок Coding Interview Prep на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Coding Interview Prep, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Coding Interview Prep содержит 4 уроков всего.

Почему на собеседованиях спрашивают об арифметике дат

Арифметика дат — один из самых практичных навыков SQL, поэтому на собеседованиях ей уделяют много внимания при подборе аналитиков и разработчиков серверной части. Почти любой бизнес-вопрос связан со временем: последние 30 дней, заказы в неделю, количество дней с момента регистрации.

Но функции работы с датами — наименее стандартизированная часть SQL. Одна и та же операция имеет разный синтаксис в PostgreSQL, MySQL и SQL Server. Хороший кандидат сначала чётко формулирует идею, а затем адаптирует синтаксис под диалект.

  • Добавление или вычитание периода
  • Вычисление разницы между двумя датами
  • Работа со значениями INTERVAL

Тип INTERVAL

В PostgreSQL и стандарте SQL период времени является полноценным значением, называемым интервалом. Вы добавляете его к дате или временной метке с помощью обычных операторов + и -.

Это самый ясный способ выразить «30 дней назад» или «через 3 месяца», и интервьюеры любят его за сходство с обычной речью.

SELECT
  CURRENT_DATE,
  CURRENT_DATE + INTERVAL '7 days'   AS next_week,
  CURRENT_DATE - INTERVAL '1 month'  AS last_month,
  NOW() + INTERVAL '90 minutes'      AS soon;

Добавление периодов в разных диалектах

Интервьюеры часто спрашивают: «как добавить 7 дней в MySQL и как — в SQL Server?» Знание трёх основных диалектов показывает практический опыт.

  • PostgreSQL: d + INTERVAL '7 days'
  • MySQL: DATE_ADD(d, INTERVAL 7 DAY)
  • SQL Server: DATEADD(day, 7, d)

Концепция одинакова; меняется только запись. Всегда указывайте диалект, для которого пишете запрос.

-- MySQL
SELECT DATE_ADD(order_date, INTERVAL 7 DAY) AS due_date FROM orders;

-- SQL Server
SELECT DATEADD(day, 7, order_date) AS due_date FROM orders;

Разница между двумя датами

Другая часть арифметики дат — вычисление расстояния между двумя датами. Результат зависит от единицы измерения и диалекта.

В PostgreSQL вычитание двух значений date непосредственно даёт целое количество дней. Вычитание двух значений timestamp вместо этого даёт интервал.

-- Postgres: date - date returns an integer (days)
SELECT shipped_date - order_date AS days_to_ship
FROM orders;

DATEDIFF и его ловушки

DATEDIFF существует в MySQL и SQL Server, но работает по-разному — это излюбленная каверза на собеседованиях.

  • MySQL: DATEDIFF(end, start) возвращает только целое количество дней.
  • SQL Server: DATEDIFF(unit, start, end) принимает единицу измерения и считает переходы через границы, а не полные единицы.

Это поведение важно: DATEDIFF(year, '2023-12-31', '2024-01-01') в SQL Server возвращает 1, хотя прошёл всего один день.

-- SQL Server: counts boundaries, not elapsed time
SELECT DATEDIFF(year, '2023-12-31', '2024-01-01'); -- 1
SELECT DATEDIFF(day,  '2023-12-31', '2024-01-01'); -- 1

Как правильно вычислять возраст в годах

«Вычислите возраст клиента в годах» — классическая задача. Наивный подход — разделить разницу в днях на 365 — даёт погрешность из-за високосных лет. В PostgreSQL есть AGE(), возвращающая настоящий календарный интервал.

Чтобы получить корректное целое число лет, извлеките из возраста его часть, соответствующую годам.

-- Postgres
SELECT
  birth_date,
  AGE(CURRENT_DATE, birth_date)               AS exact_age,
  EXTRACT(YEAR FROM AGE(CURRENT_DATE, birth_date)) AS age_years
FROM customers;

Практический пример: заказы за последние 30 дней

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

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

SELECT COUNT(*) AS recent_orders
FROM orders
WHERE order_date >= CURRENT_DATE - INTERVAL '30 days';

Полуоткрытые диапазоны для календарного месяца

Когда Вас просят найти «все заказы за март 2024 года», не используйте BETWEEN '2024-03-01' AND '2024-03-31' для столбца с временными метками. Такой подход может пропустить записи за 23:00 31 марта и легко приводит к ошибке на единицу.

Надёжный шаблон — полуоткрытый интервал: >= для начала и < для начала следующего месяца. Он работает при любой точности столбца.

SELECT *
FROM orders
WHERE order_ts >= DATE '2024-03-01'
  AND order_ts <  DATE '2024-04-01';

EXTRACT и компоненты даты

Извлечение отдельного компонента даты — регулярная задача в отчётах. Стандартная функция — EXTRACT(part FROM d), поддерживаемая PostgreSQL и MySQL.

  • EXTRACT(YEAR FROM d), MONTH, DAY
  • EXTRACT(DOW FROM d) для получения дня недели
  • В SQL Server вместо этого используется DATEPART(weekday, d)

Обратите внимание: извлечение только MONTH объединяет мартовские даты из разных лет, что редко соответствует цели.

SELECT
  EXTRACT(YEAR  FROM order_ts) AS yr,
  EXTRACT(MONTH FROM order_ts) AS mo,
  COUNT(*) AS n
FROM orders
GROUP BY 1, 2
ORDER BY 1, 2;

Более сложный пример: количество дней до следующего дня рождения

Это более сложная задача на арифметику, объединяющая извлечение и сложение. Сформируйте день рождения в этом году по месяцу и дню рождения, а если он уже прошёл, перенесите расчёт на следующий год.

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

-- Postgres
SELECT
  name,
  CASE
    WHEN MAKE_DATE(EXTRACT(YEAR FROM CURRENT_DATE)::int,
                   EXTRACT(MONTH FROM birth_date)::int,
                   EXTRACT(DAY FROM birth_date)::int) >= CURRENT_DATE
    THEN MAKE_DATE(EXTRACT(YEAR FROM CURRENT_DATE)::int,
                   EXTRACT(MONTH FROM birth_date)::int,
                   EXTRACT(DAY FROM birth_date)::int) - CURRENT_DATE
    ELSE MAKE_DATE(EXTRACT(YEAR FROM CURRENT_DATE)::int + 1,
                   EXTRACT(MONTH FROM birth_date)::int,
                   EXTRACT(DAY FROM birth_date)::int) - CURRENT_DATE
  END AS days_until
FROM customers;

Первый и последний день месяца

«Назовите последний день месяца для каждого заказа» — такая задача проверяет, используете ли Вы встроенную функцию или пытаетесь заново реализовать её. В PostgreSQL DATE_TRUNC сочетается с арифметикой интервалов; в MySQL есть готовая функция LAST_DAY().

Хитрость для получения последнего дня в PostgreSQL: усечь дату до начала месяца, прибавить один месяц и вычесть один день.

-- Postgres
SELECT
  DATE_TRUNC('month', order_ts)                              AS month_start,
  DATE_TRUNC('month', order_ts) + INTERVAL '1 month - 1 day' AS month_end
FROM orders;

-- MySQL: LAST_DAY(order_ts)

Быстрая проверка

Проверьте, понимаете ли Вы, как в разных диалектах вычисляется разница дат.

Итоги: арифметика дат и интервалы

Главные выводы для собеседования:

  • Используйте значения INTERVAL с операторами +/- в PostgreSQL; DATE_ADD/DATEDIFF в MySQL; DATEADD/DATEDIFF в SQL Server.
  • DATEDIFF в SQL Server считает переходы через границы, а не прошедшие единицы измерения — это главная ловушка.
  • Для вычисления возраста в годах извлекайте данные из AGE(), а не делите число дней на 365.
  • Фильтруйте недавние строки, сравнивая столбец с вычисленной границей, и используйте полуоткрытые диапазоны (>= start AND < next) для месячных интервалов.

Сначала сформулируйте концепцию, затем адаптируйте синтаксис под диалект.

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

Урок «Арифметика дат и интервалы» бесплатный?

Да — полный текст урока «Арифметика дат и интервалы» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Coding Interview Prep, подпишись на CoddyKit PRO. Курс Coding Interview Prep содержит 4 уроков всего.

Чему я научусь в уроке «Арифметика дат и интервалы»?

Сложение и вычитание периодов, а также вычисление разницы между датами Ты практикуешь Coding Interview Prep с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.

Нужен ли мне опыт, чтобы начать Coding Interview Prep?

Предыдущий опыт не требуется. Coding Interview Prep на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.

Сколько времени занимает урок «Арифметика дат и интервалы»?

Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.

Можно ли писать и запускать код в этом уроке Coding Interview Prep?

Да. Каждый урок Coding Interview Prep включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.

Все уроки этого курса

  1. Арифметика дат и интервалы
  2. Округление дат и распределение по интервалам
  3. Разбор и форматирование строк
  4. Часовые пояса и временные метки
← Назад к Coding Interview Prep