Собесов

LeetCode SQL — Active Users: 5 подряд логинов (gaps & islands)

SQLГруппировка по сериямСредняяMiddle

Условие

Таблицы:

  • Accounts(id, name)
  • Logins(id, login_date)id ссылается на Accounts.id. Возможны дубли (один пользователь — несколько входов в день).

Активный пользователь — тот, у кого есть серия из 5 и более подряд идущих дней с логином. Верните id, name, отсортируйте по id.

Решение

Идея — классический gaps & islands

Сводим логины к DISTINCT (id, login_date), вычитаем ROW_NUMBER() (умноженный на день) из даты — внутри одной серии разность константна.

WITH distinct_logins AS (
  SELECT DISTINCT id, login_date
  FROM Logins
),
grouped AS (
  SELECT
    id,
    login_date,
    login_date - ROW_NUMBER() OVER (PARTITION BY id ORDER BY login_date) * INTERVAL '1 day'
      AS streak_key
  FROM distinct_logins
),
streaks AS (
  SELECT id, streak_key, COUNT(*) AS streak_len
  FROM grouped
  GROUP BY id, streak_key
)
SELECT DISTINCT a.id, a.name
FROM streaks s
JOIN Accounts a ON a.id = s.id
WHERE s.streak_len >= 5
ORDER BY a.id;

Альтернатива через DATEDIFF между соседями

WITH d AS (
  SELECT DISTINCT id, login_date FROM Logins
),
lagged AS (
  SELECT
    id, login_date,
    SUM(CASE WHEN login_date = prev + 1 THEN 0 ELSE 1 END)
      OVER (PARTITION BY id ORDER BY login_date) AS grp
  FROM (
    SELECT id, login_date,
           LAG(login_date) OVER (PARTITION BY id ORDER BY login_date) AS prev
    FROM d
  ) t
)
SELECT DISTINCT a.id, a.name
FROM (
  SELECT id, grp, COUNT(*) AS len
  FROM lagged GROUP BY id, grp
) s
JOIN Accounts a ON a.id = s.id
WHERE s.len >= 5
ORDER BY a.id;

Подводные камни

  1. DISTINCT обязателен. Без него один день с двумя логинами разваливает шаг.
  2. >= vs = 5. Условие — «как минимум 5», а не «ровно 5».
  3. Сортировка. Финальный ORDER BY id — в задаче явно требуется.

Эталонный ответ

Gaps & islands. Distinct → ROW_NUMBER → date - rn*day → группа по streak_key → фильтр по COUNT(*) >= 5. Заработает в любой СУБД, только синтаксис интервалов разный.

Хочешь увидеть разбор?

Зарегистрируйся бесплатно — откроется развёрнутое решение этой задачи и ещё 4 на выбор.

Зарегистрироваться и увидеть разбор
Уже есть аккаунт? Войти