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

Серии подряд идущих дней в SQL

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

  • ЯзыкSQL
  • УровеньПродвинутый
  • НавыкGaps and Islands и оконные функции

Серии подряд идущих дней

Контекст

Финал разбора журнала: вместо отдельных дат руководителю нужны отрезки непрерывной работы — с какого по какое число человек выходил без единого пропуска и сколько это дней. Одна и та же таблица отметок, но смотреть на неё надо не по строкам, а по цепочкам.

Задача

Верните все серии подряд идущих дней с отметкой по каждому сотруднику: начало, конец и длину серии.

Данные

Таблица attendance — отметки присутствия (одна строка = один день):

колонкатипчто хранит
employee_idintномер сотрудника, ссылка на employees.id
work_daydateдень, когда сотрудник отметился

Таблица employees — сотрудники: id, name, department_id, manager_id, job_title, salary, hired_at, left_at.

Примерные строки attendance (сотрудник 3):

employee_idwork_day
32026-06-08
32026-06-09
32026-06-12

Правила

  1. Колонки: employee (имя), started_at, ended_at, length.
  2. Серия — это дни одного сотрудника, идущие подряд без пропусков. Первый же пропущенный день серию обрывает, и следующая начинается заново.
  3. length — сколько дней в серии; оба конца считаются. Одна отметка даёт серию длиной 1, где начало и конец совпадают.
  4. Серии считаются внутри одного сотрудника: одинаковые дни у разных людей — это разные серии.
  5. Сортировка: started_at по возрастанию, при равенстве — имя по алфавиту.

Примеры

-- Выдача на данных «Пульса»:
-- employee       | started_at | ended_at   | length
-- Вика Носова    | 2026-06-01 | 2026-06-14 | 14
-- Данил Крылов   | 2026-06-01 | 2026-06-02 | 2
-- Игорь Соловьёв | 2026-06-01 | 2026-06-09 | 9
-- Настя Ким      | 2026-06-01 | 2026-06-26 | 26
-- Данил Крылов   | 2026-06-04 | 2026-06-15 | 12
-- Игорь Соловьёв | 2026-06-12 | 2026-06-26 | 15
-- Алина Юсупова  | 2026-06-17 | 2026-06-17 | 1
-- Данил Крылов   | 2026-06-18 | 2026-06-26 | 9

-- У Данила Крылова три серии: два дня, потом двенадцать, потом девять.

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

Так считают серии дней активности в подписке, непрерывные периоды работы сервиса и любые «сколько дней подряд». Здесь важно не смешать сотрудников, корректно обработать одиночную отметку и разорвать интервал на первом пропущенном дне.

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

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

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

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

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

CREATE TABLE employees (
  id INTEGER PRIMARY KEY,
  name TEXT NOT NULL,
  department_id INTEGER NOT NULL,
  manager_id INTEGER,
  job_title TEXT NOT NULL,
  salary INTEGER,
  hired_at DATE NOT NULL,
  left_at DATE
);


CREATE TABLE attendance (
  employee_id INTEGER NOT NULL,
  work_day DATE NOT NULL,
  PRIMARY KEY (employee_id, work_day)
);

INSERT INTO employees
  (id, name, department_id, manager_id, job_title, salary, hired_at, left_at)
VALUES
  (1, 'Анна', 1, NULL, 'Инженер', 200000, DATE '2024-01-01', NULL),
  (2, 'Борис', 1, NULL, 'Аналитик', 210000, DATE '2024-02-01', NULL);

INSERT INTO attendance (employee_id, work_day) VALUES
  (1, DATE '2026-02-01'),
  (1, DATE '2026-02-02'),
  (1, DATE '2026-02-04'),
  (2, DATE '2026-02-01'),
  (2, DATE '2026-02-02'),
  (2, DATE '2026-02-03');
Ожидаемый результат
employeestarted_atended_atlength
Анна2026-02-012026-02-022
Борис2026-02-012026-02-033
Анна2026-02-042026-02-041

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

Подсказка 1

Выполняйте расчёт отдельно для каждого сотрудника.

Подсказка 2

Найдите признак, который будет одинаковым у соседних дней одной серии.

Подсказка 3

После группировки посчитайте оба конца интервала и задайте итоговую сортировку.

Как найти непрерывные серии дат

Серия — максимальный непрерывный интервал дат одного сотрудника. Важно не смешать людей и учесть одиночные дни.

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