Вопросы по теме «Даты и время»
Работа с датами в SQL — это DATE_TRUNC, EXTRACT, интервалы, приведение типов и группировка по временным периодам. На собеседованиях часто просят посчитать метрику по неделям или месяцам, найти разницу между датами, или отфильтровать данные за скользящее окно. Ошибки в работе с таймзонами и форматами дат — частая причина провала на интервью.
Всего в этом разделе 20 вопросов. Каждый — с правильным ответом и кратким разбором теории. Разбито на 4 части по 5 вопросов.
Вопросы 1–5 из 20
1Как получить начало текущей недели (недельный бакет) по текущей дате в PostgreSQL?
A`DATE_TRUNC('day', current_date)`
B`DATE_TRUNC('month', current_date)`
C`current_date - INTERVAL '7 days'`
D`DATE_TRUNC('week', current_date)`
Ответ: `DATE_TRUNC('week', ...)` возвращает метку начала недели.
Функция `DATE_TRUNC` обрезает дату/время до начала указанного периода. Для недельных бакетов используйте `DATE_TRUNC('week', current_date)` (в PostgreSQL неделя начинается в понедельник).
2В таблице `events(user_id, created_at)` поле `created_at` типа `timestamp`. Как посчитать количество событий по дням?
A`SELECT created_at, COUNT(*) FROM events GROUP BY created_at;`
B`SELECT DATE_TRUNC('day', created_at) AS day, COUNT(*) FROM events GROUP BY DATE_TRUNC('day', created_at);`
C`SELECT DATE_TRUNC('day', created_at) AS day, COUNT(*) FROM events;`
D`SELECT DATE_TRUNC('month', created_at) AS day, COUNT(*) FROM events GROUP BY DATE_TRUNC('month', created_at);`
Ответ: `DATE_TRUNC('day', ...)` обрезает время до начала дня и подходит для группировки по дням.
Для бакетирования по дням используйте `DATE_TRUNC('day', created_at)` и группируйте по этому же выражению. Группировка по самому `created_at` даст отдельную группу на каждую уникальную метку времени.
3Нужно построить график регистраций по часам из таблицы `users(created_at)`, где `created_at` типа `timestamp`. Какой бакет лучше использовать?
A`DATE_TRUNC('day', created_at)`
B`DATE_TRUNC('hour', created_at)`
C`DATE_TRUNC('minute', created_at)`
D`EXTRACT(HOUR FROM created_at)`
Ответ: Часовой бакет делается через `DATE_TRUNC('hour', ...)`, чтобы сохранить и дату, и час.
Если извлечь только час через `EXTRACT(HOUR FROM created_at)`, вы потеряете дату и смешаете разные дни в один и тот же час. `DATE_TRUNC('hour', created_at)` сохраняет дату и обнуляет минуты/секунды, создавая корректные часовые бакеты.
4Нужно получить колонку `event_date` типа `date` из `created_at` (тип `timestamp`) для `JOIN` с календарной таблицей по дате. Какое выражение подойдёт лучше всего?
A`created_at::date`
B`DATE_TRUNC('day', created_at)`
C`EXTRACT(DAY FROM created_at)`
D`DATE_TRUNC('month', created_at)::date`
Ответ: Если нужен именно тип `date`, используйте приведение `::date`.
`DATE_TRUNC('day', created_at)` даёт начало дня, но возвращает `timestamp`. Для `JOIN` с календарём, где ключ обычно типа `date`, удобнее сразу получить `created_at::date`.
5Как сгруппировать заказы из таблицы `orders(created_at)` по кварталам с помощью `DATE_TRUNC`?
A`SELECT DATE_TRUNC('quarter', created_at) AS q, COUNT(*) FROM orders GROUP BY DATE_TRUNC('quarter', created_at);`
B`SELECT DATE_TRUNC('month', created_at) AS q, COUNT(*) FROM orders GROUP BY DATE_TRUNC('month', created_at);`
C`SELECT created_at + INTERVAL '3 months' AS q, COUNT(*) FROM orders GROUP BY created_at + INTERVAL '3 months';`
D`SELECT EXTRACT(QUARTER FROM created_at) AS q, COUNT(*) FROM orders GROUP BY EXTRACT(QUARTER FROM created_at);`
Ответ: `DATE_TRUNC('quarter', ...)` возвращает начало квартала и подходит для квартальных бакетов.
Для квартальной агрегации удобнее использовать `DATE_TRUNC('quarter', created_at)`, потому что результат — конкретная дата/время начала квартала (например, 1 января или 1 апреля). Это лучше для последующих `JOIN` и сортировок, чем просто номер квартала без года.
Хотите тренировать интерактивно?
В приложении — таймер, прогресс, стрики и 1700+ вопросов по всем темам.
Тренировать в Telegram