🔥 Live Coding: сотрудники, которые работали в марте 2025 и получили salary_change > 200000

Задача: Есть 2 таблицы.

employees • employee_id • hire_date • fire_date • department_id

employee_events • employee_id • event_time • event_type • salary

Нужно найти сотрудников, которые:

• работали в марте 2025 • у которых последнее кадровое событие — salary_change • и зарплата после него больше 200000

На выходе хотим получить:

• employee_id • salary • event_time

Решение:

with active_in_march as ( select employee_id from employees where hire_date <= toDate('2025-03-31') and (fire_date is null or fire_date >= toDate('2025-03-01')) ),

last_event as ( select employee_id, event_time, event_type, salary, row_number() over ( partition by employee_id order by event_time desc ) as rn from employee_events )

select l.employee_id, l.salary, l.event_time from last_event l inner join active_in_march a on l.employee_id = a.employee_id where l.rn = 1 and l.event_type = 'salary_change' and l.salary > 200000

🧠 Как здесь думаем:

Сначала отдельно определяем сотрудников, которые пересекались с мартом 2025.

Логика такая: если сотрудник нанят не позже 31 марта 2025 и уволен либо после 1 марта 2025, либо вообще не уволен, значит он работал в марте ✅

Это классическая проверка пересечения интервалов.

Дальше по таблице employee_events ищем последнее событие по каждому сотруднику. Для этого используем:

• partition by employee_id • order by event_time desc • row_number()

Строка с rn = 1 — это последнее событие сотрудника.

После этого оставляем только тех, у кого:

• последнее событие = salary_change • salary > 200000

⚠️ Где можно ошибиться:

Неправильно проверить “работал в марте”

Частая ошибка — фильтровать только тех, кто был нанят именно в марте или уволен именно в марте.

Но нам нужны все, кто хотя бы частично работал в этом месяце. То есть проверяем именно пересечение интервала работы с мартом.

Взять последнее salary_change, а не последнее событие вообще

По условию нужно: “последнее событие — salary_change”

Это значит, что если после salary_change был, например, transfer, такой сотрудник уже не подходит ❌

Не продумать дедуп событий

Если у сотрудника много событий, простой join без оконной функции даст несколько строк. Поэтому здесь нужна явная дедупликация через row_number().

💡 Если у двух событий одного сотрудника одинаковый event_time, лучше добавить дополнительный tie-breaker в order by. Например, event_id, если он есть. Иначе “последнее” событие может определяться неоднозначно.

Например так:

row_number() over ( partition by employee_id order by event_time desc, event_id desc ) as rn

🎯 Вывод:

Это хорошая задача на 3 вещи сразу:

• интервалы дат • дедупликацию событий • точную бизнес-логику “последнего состояния”

Здесь важно не просто найти salary_change, а доказать, что это именно последнее событие сотрудника.

Именно на таких деталях чаще всего и ломается логика запроса 👌

🔥 Live Coding: сотрудники, которые работали в марте 2025 и получили salarychange > 200000
Задача:
Есть 2 таблицы | Сетка — социальная сеть от hh.ru