Даты и время: вопросы для собеседования (часть 2)

Работа с датами в SQL — это DATE_TRUNC, EXTRACT, интервалы, приведение типов и группировка по временным периодам. На собеседованиях часто просят посчитать метрику по неделям или месяцам, найти разницу между датами, или отфильтровать данные за скользящее окно. Ошибки в работе с таймзонами и форматами дат — частая причина провала на интервью.

Агрегация, GROUP BY и HAVINGEXPLAIN и оптимизацияВыражения и NULLJOIN и операции множествОсновы SQL-запросовСтроки и приведение типовПодзапросы и CTEОконные функции

Вопросы 610 из 20

6Колонка `created_at` имеет тип `timestamp`. Какой тип данных вернёт `DATE_TRUNC('day', created_at)`?
AТип `timestamp`: время будет `00:00:00` для выбранного дня, тип входа сохраняется на выходе
BТип `date`: только календарная дата без компоненты времени, остаётся одно значение даты
CЦелое число `int`: порядковый номер дня в месяце, полученный из исходного значения `timestamp`
DСтроку формата `'YYYY-MM-DD'`: текстовое представление даты в типе `text` или `varchar`
Ответ: `DATE_TRUNC` сохраняет тип `timestamp` и обнуляет более мелкие компоненты времени.

При входе типа `timestamp` результат `DATE_TRUNC('day', created_at)` тоже будет `timestamp`, но с временем начала дня `00:00:00`. Если нужен именно `date`, добавьте приведение `created_at::date` или оборачивайте `DATE_TRUNC` в `CAST`. Целое число или строка — типы, которые `DATE_TRUNC` не возвращает.

Подробный разбор →
7Колонка `created_at` типа `timestamp`. Какое утверждение про `created_at::date` и `DATE_TRUNC('day', created_at)` верно?
A`created_at::date` отдаёт `timestamp`, а `DATE_TRUNC('day', created_at)` отдаёт `date`
B`created_at::date` возвращает тип `date`, а `DATE_TRUNC('day', created_at)` возвращает `timestamp`
C`DATE_TRUNC('day', created_at)` округляет до ближайшего дня, а `created_at::date` обрезает время
DОба выражения возвращают тип `date` и одинаковое значение для любых входных `timestamp`
Ответ: Приведение `::date` меняет тип, а `DATE_TRUNC` сохраняет `timestamp` и обнуляет время ниже указанной гранулярности.

При `created_at::date` вы получаете календарную дату без времени, тип результата — `date`. `DATE_TRUNC('day', created_at)` возвращает `timestamp` на `00:00:00` этого дня, тип сохраняется. Это влияет на формат результата и на дальнейшие сравнения и вычисления — например, при `JOIN` по дате типы должны совпадать.

Подробный разбор →
8Есть таблица `orders(created_at, amount)`, где `created_at` имеет тип `timestamp`. Как посчитать выручку по месяцам?
A`SELECT DATE_TRUNC('month', created_at) AS m, SUM(amount) FROM orders GROUP BY DATE_TRUNC('month', created_at);`
B`SELECT DATE_TRUNC('month', created_at) AS m, amount FROM orders GROUP BY DATE_TRUNC('month', created_at);`
C`SELECT DATE_TRUNC('month', created_at) AS m, SUM(amount) FROM orders ORDER BY DATE_TRUNC('month', created_at);`
D`SELECT DATE_TRUNC('day', created_at) AS m, SUM(amount) FROM orders GROUP BY DATE_TRUNC('month', created_at);`
Ответ: Для метрик по периодам вычислите бакет через `DATE_TRUNC` и агрегируйте с `GROUP BY` по этому бакету.

Чтобы получить выручку по месяцам, сформируйте месячный бакет `DATE_TRUNC('month', created_at)` и посчитайте `SUM(amount)`. В `GROUP BY` нужно повторить то же выражение, что используется для бакета. Без агрегата `SUM` будет просто список заказов, а с днём в `SELECT` и месяцем в `GROUP BY` запрос вернёт ошибку или некорректный результат.

Подробный разбор →
9В таблице `events(created_at)` нужно выбрать события за последние 7 дней с точностью до текущего момента (включая сегодняшние, ещё не завершённые сутки). Какое условие в `WHERE` корректнее?
A`WHERE created_at >= current_timestamp - INTERVAL '7 days'`
B`WHERE created_at >= current_date - INTERVAL '7 days'`
C`WHERE DATE_TRUNC('day', created_at) >= current_timestamp - INTERVAL '7 days'`
D`WHERE created_at <= current_timestamp - INTERVAL '7 days'`
Ответ: Для скользящего окна «последние 7 дней до текущего момента» используют `current_timestamp - INTERVAL '7 days'`.

`current_timestamp` возвращает момент с временем, поэтому `created_at >= current_timestamp - INTERVAL '7 days'` отбирает события за последние 7×24 часа. `current_date` обнуляет время до полуночи и подходит для календарных периодов («с начала дня семь дней назад»), но смещает границу окна. Вариант с `DATE_TRUNC` сравнивает день с моментом времени и теряет внутренний интервал. Условие `<=` берёт всё старше 7 дней, то есть зеркально неправильное окно.

Подробный разбор →
10Для сравнения метрик по неделям нужно получить начало предыдущей недели. Какое выражение вернёт начало предыдущей недели относительно `current_date`?
A`DATE_TRUNC('week', current_date) - INTERVAL '1 week'`
B`DATE_TRUNC('week', current_date) - INTERVAL '1 day'`
C`DATE_TRUNC('month', current_date) - INTERVAL '1 week'`
D`current_date - INTERVAL '1 week'`
Ответ: Найдите начало текущей недели через `DATE_TRUNC`, затем сдвиньте на `INTERVAL '1 week'` назад.

Чтобы корректно сравнивать недели, важно фиксировать границы бакетов. `DATE_TRUNC('week', current_date)` даёт начало текущей недели, а `- INTERVAL '1 week'` — начало предыдущей.

Подробный разбор →
1234

Хотите тренировать интерактивно?

В приложении — таймер, прогресс, стрики и 1700+ вопросов по всем темам.

Тренировать SQL в Telegram

Другие темы: SQL

Агрегация, GROUP BY и HAVINGEXPLAIN и оптимизацияВыражения и NULLJOIN и операции множествОсновы SQL-запросовСтроки и приведение типовПодзапросы и CTEОконные функции