// практика без регистрации

Кандидаты с повторными откликами

Соберите повторные отклики по email и покажите диапазон дат для каждого найденного дубля.

  • ЯзыкSQL
  • УровеньСредний
  • НавыкGROUP BY, HAVING и агрегатные функции

Кандидаты с повторными откликами

Контекст

Рекрутеры «Пульса» жалуются: один и тот же человек подаётся по нескольку раз, и его карточка всплывает в воронке дважды. Прежде чем чистить базу, нужно понять масштаб — с каких почт пришло больше одного отклика и как далеко разъехались даты.

Задача

Верните почты, с которых пришло больше одного отклика, со счётчиком и датами первого и последнего.

Данные

Таблица applications — отклики кандидатов:

колонкатипчто хранит
idintномер отклика
candidatetextимя кандидата
emailtextпочта, NULL если кандидат пришёл без контакта
department_idintотдел, куда откликнулись
applied_atdateдата отклика
stagetextстадия: new / screening / tech / offer / hired / rejected
sourcetextисточник: hh / telegram / referral / site

Примерные строки:

idcandidateemailapplied_atstage
1Сергей Соколовsokolov@mail.example2026-03-02hired
6Сергей Соколовsokolov@mail.example2026-04-15rejected
15Роман ГуляевNULL2026-06-15new
18Илья КрайновNULL2026-06-29new

Правила

  1. Колонки: email, applications_count, first_applied, last_applied.
  2. Выводим почту, если с неё пришло два отклика или больше.
  3. Отклики без почты (email IS NULL) не участвуют: контакта нет, склеивать такие отклики между собой нельзя.
  4. Почта сравнивается как есть, посимвольно: Sokolov@mail.example и sokolov@mail.example — разные кандидаты, приводить регистр не нужно.
  5. first_applied — самая ранняя дата отклика с этой почты, last_applied — самая поздняя.
  6. Сортировка: счётчик по убыванию, при равенстве — почта по алфавиту.

Примеры

-- Выдача на данных «Пульса»:
-- email                | applications_count | first_applied | last_applied
-- sokolov@mail.example | 2                  | 2026-03-02    | 2026-04-15
-- vetrova@mail.example | 2                  | 2026-03-19    | 2026-06-27

Где это пригодится

Поиск повторов по ключу — первый шаг любой чистки данных: одинаковые заказы, задвоенные платежи, один и тот же клиент под двумя записями. Ловушка всегда одна и та же: NULL (значение «неизвестно»; два NULL не равны друг другу) в ключе группировки собирается в одну кучу, хотя за ним стоят разные люди.

Данные для локальной проверки

Каждый набор запускается в отдельной базе. Здесь показаны точные данные, на которых проверяется запрос.

Порядок строк в результате важен.

Набор 1: данные и ожидаемый результат

Таблицы и данные

CREATE TABLE applications (
  id INTEGER PRIMARY KEY,
  candidate TEXT NOT NULL,
  email TEXT,
  department_id INTEGER NOT NULL,
  applied_at DATE NOT NULL,
  stage TEXT NOT NULL,
  source TEXT NOT NULL
);

INSERT INTO applications
  (id, candidate, email, department_id, applied_at, stage, source)
VALUES
  (1, 'Анна', 'anna@example.test', 1, DATE '2026-01-03', 'new', 'site'),
  (2, 'Борис', 'boris@example.test', 2, DATE '2026-01-04', 'new', 'referral'),
  (3, 'Анна', 'anna@example.test', 1, DATE '2026-01-10', 'screening', 'site'),
  (4, 'Анна', 'anna@example.test', 1, DATE '2026-01-18', 'tech', 'site'),
  (5, 'Борис', 'boris@example.test', 2, DATE '2026-01-15', 'tech', 'referral'),
  (6, 'Соло', 'solo@example.test', 3, DATE '2026-01-09', 'new', 'hh'),
  (7, 'Без почты А', NULL, 1, DATE '2026-01-11', 'new', 'site'),
  (8, 'Без почты Б', NULL, 2, DATE '2026-01-12', 'new', 'site');
Ожидаемый результат
emailapplications_countfirst_appliedlast_applied
anna@example.test32026-01-032026-01-18
boris@example.test22026-01-042026-01-15

Двигайтесь по одному шагу

Подсказка 1

Исключите строки без email до группировки.

Подсказка 2

Считайте строки внутри каждой группы и фильтруйте результат через HAVING.

Подсказка 3

Задайте алиасы колонок и итоговую сортировку точно по контракту.

Как отфильтровать группы после подсчёта

WHERE исключает строки до группировки, а HAVING оставляет только группы с нужным количеством записей.

Продолжите практику