유저별 최장 연속 거래일수

난이도 어려움 · 권장 18분 · 출력 컬럼 user_id, max_streak_days
이 문제 직접 풀어보기 →

문제

stock_orders 에서 유저별 '가장 길게 연속으로 거래한 일수' 를 구하고, 그 값이 3 이상인 유저만 뽑으세요. user_id max_streak_days 최장 연속 거래일수 · status = 'COMPLETED' 인 주문만 셉니다. · 하루에 여러 번 거래했어도 그 날은 1일입니다. · 그 날 주문이 전부 CANCELLED 면 거래하지 않은 날입니다 (연속이 끊깁니다). · 날짜가 하루씩 이어진 구간만 연속입니다. 주말·공휴일은 따지지 않습니다. · max_streak_days 내림차순, 같으면 user_id 오름차순으로 정렬하세요.
정렬 max_streak_days DESC, user_id ASC

쉽게 설명하면

Q8 의 출석 도장 트릭과 똑같다. 단위가 '달' 에서 '날' 로 바뀐 것뿐.

거래한 날날 번호줄 번호차이
3월 2일60159
3월 3일61259
3월 4일62359
3월 8일66462

차이 59 가 세 개 → 3연속. 그 다음은 끊긴 것.

이렇게 푼다

  1. 성공한 주문만 남기고, 하루는 1번으로 중복을 지운다. 이 한 줄에 문제 조건 두 개가 다 들어 있다.
  2. 날짜를 숫자로 바꾼다.
  3. 날 숫자 − 줄 번호 → 묶어서 개수 → 사람별 최대값 → 3 이상만.

이것만 피하면 된다

자세히

묻는 것 · gaps and islands. 알면 2분, 모르면 못 푼다. 반드시 외워 둘 패턴.

풀이 순서

  1. 먼저 조건을 걸고 하루 단위로 중복을 지운다: SELECT DISTINCT user_id, order_date ... WHERE status='COMPLETED'. 이 한 줄에 문제의 조건 두 개가 다 들어 있다.
  2. 날짜를 일련번호로 바꾼다: DATEDIFF(order_date, '기준일').
  3. 일련번호 − ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY order_date) → 연속 구간마다 같은 값이 나온다.
  4. 그 값으로 묶어 COUNT(*) → 구간 길이. 유저별 MAX() → 최장 길이. HAVING 으로 3 이상만.

정답 (MySQL)

WITH d AS (
  SELECT DISTINCT user_id, order_date
  FROM stock_orders
  WHERE status = 'COMPLETED'
),
g AS (
  SELECT user_id, order_date,
         DATEDIFF(order_date, '2026-01-01')
         - ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY order_date) AS grp
  FROM d
),
runs AS (
  SELECT user_id, grp, COUNT(*) AS run_len
  FROM g GROUP BY user_id, grp
)
SELECT user_id, MAX(run_len) AS max_streak_days
FROM runs
GROUP BY user_id
HAVING MAX(run_len) >= 3
ORDER BY max_streak_days DESC, user_id ASC;

함정

이렇게 변형된다

“연속 출석일수”, “N일 연속 접속”, “연속 결제 개월수” 전부 같은 패턴이다. 월 단위면 일련번호를 TIMESTAMPDIFF(MONTH, 기준월, 그달) 로 바꾼다. “현재 진행 중인 연속일수”면 마지막 구간만 (MAX(order_date) = 오늘 인 구간) 남긴다.

← Q14. 코호트별 D7 리텐션율Q16. A/B 테스트 그룹 집계 (상위 1% 제외) →