Арифметика дат и интервалы
Сложение и вычитание периодов, а также вычисление разницы между датами
«Арифметика дат и интервалы» — бесплатный урок SQL Interview Prep на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения SQL Interview Prep, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс SQL 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,DAYEXTRACT(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) и разблокировать остальной курс SQL Interview Prep, подпишись на CoddyKit PRO. Курс SQL Interview Prep содержит 4 уроков всего.
Чему я научусь в уроке «Арифметика дат и интервалы»?
Сложение и вычитание периодов, а также вычисление разницы между датами Ты практикуешь SQL Interview Prep с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать SQL Interview Prep?
Предыдущий опыт не требуется. SQL Interview Prep на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «Арифметика дат и интервалы»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке SQL Interview Prep?
Да. Каждый урок SQL Interview Prep включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Арифметика дат и интервалы
- Округление дат и распределение по интервалам
- Разбор и форматирование строк
- Часовые пояса и временные метки