0Pricing
SQL Interview Prep · 강의

날짜와 상태 변화가 있는 아일랜드

연속된 동일 상태 기간을 그룹화합니다. 구독 상태에서 자주 나오는 문제입니다.

날짜와 상태 변화가 있는 아일랜드은(는) CoddyKit의 무료 SQL Interview Prep 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 SQL Interview Prep 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. SQL Interview Prep 강의에는 총 4개의 강의가 포함되어 있습니다.

변하는 값으로 정의되는 연속 구간

실무에서 가장 중요한 누락과 연속 구간 문제는 같은 상태를 공유하는 연속된 행을 하나로 묶어, 잡음이 많은 이벤트 기록을 깔끔한 상태 기간으로 정리하는 것입니다. 대표적인 질문은 다음과 같습니다. “구독 이벤트 기록이 주어졌을 때, 사용자가 각 상태에 머문 연속 기간마다 한 행씩 반환하십시오.”

여기서 인접함은 ‘값이 1만큼 차이 나는 것’을 의미하지 않습니다. 이전 행과 상태가 변하지 않은 것을 의미합니다. 상태가 바뀌는 순간 새로운 연속 구간이 시작됩니다. 이 경우에는 순수한 행 번호 차이 기법보다 LAG 기반 기법이 더 효과적입니다.

구독 예시

한 사용자의 날짜순으로 정렬된 sub_events 테이블을 생각해 보십시오.

  • 2026-01-01 활성
  • 2026-02-01 활성
  • 2026-03-01 일시 중지
  • 2026-04-01 활성
  • 2026-05-01 활성

원하는 결과는 세 개의 상태 기간입니다. 1월-2월 활성, 3월 일시 중지, 4월-5월 활성입니다. 두 활성 기간 사이에 일시 중지 기간이 끼어 있으므로 서로 별도의 연속 구간이라는 점에 주목하십시오. 상태는 같더라도 연속되지 않으면 서로 다른 연속 구간입니다.

CREATE TABLE sub_events (
  user_id INT, status TEXT, event_date DATE
);
INSERT INTO sub_events VALUES
 (1,'active','2026-01-01'),(1,'active','2026-02-01'),
 (1,'paused','2026-03-01'),(1,'active','2026-04-01'),
 (1,'active','2026-05-01');

상태가 바뀌는 위치 표시하기

LAG를 사용하여 각 행의 상태를 이전 행의 상태와 비교하십시오. 두 상태가 다르거나 첫 행처럼 이전 값이 NULL이면 새로운 연속 구간이 시작됩니다. 상태가 바뀌면 1, 그렇지 않으면 0을 기록합니다.

사용자 내에서 날짜순으로 엄격하게 정렬하십시오. 이 데이터의 상태 변경 표시값은 1, 0, 1, 1, 0이며, 세 기간의 경계를 나타냅니다.

SELECT
  user_id, status, event_date,
  CASE
    WHEN status = LAG(status)
      OVER (PARTITION BY user_id ORDER BY event_date)
    THEN 0 ELSE 1
  END AS is_change
FROM sub_events;

누적합으로 기간 키 만들기

앞에서와 마찬가지로 상태 변경 표시값의 누적합을 구하면 각 상태 기간 안에서 일정한 그룹 키가 만들어집니다. 이 데이터에서는 1, 1, 2, 3, 3입니다. 서로 다른 각 키가 하나의 연속 기간입니다.

상태는 1씩 증가하는 숫자가 아니므로 행 번호 차이 기법은 여기서 작동하지 않습니다. 인접함이 ‘값이 변하지 않은 것’을 의미할 때는 LAG와 누적합을 조합하는 방법이 올바른 도구입니다.

WITH flagged AS (
  SELECT user_id, status, event_date,
    CASE WHEN status = LAG(status)
           OVER (PARTITION BY user_id ORDER BY event_date)
         THEN 0 ELSE 1 END AS is_change
  FROM sub_events
)
SELECT user_id, status, event_date,
  SUM(is_change)
    OVER (PARTITION BY user_id ORDER BY event_date) AS grp
FROM flagged;

상태 기간으로 합치기

이제 user_id, status, 누적합 키로 GROUP BY하여 각 기간의 범위를 보고하십시오. 상태는 기간 내에서 일정하므로 GROUP BY에 포함해도 안전하며, 집계 함수 없이 상태를 선택할 수도 있습니다.

결과는 정확히 세 행입니다. 활성 01-01부터 02-01, 일시 중지 03-01부터 03-01, 활성 04-01부터 05-01입니다.

WITH flagged AS (
  SELECT user_id, status, event_date,
    CASE WHEN status = LAG(status)
           OVER (PARTITION BY user_id ORDER BY event_date)
         THEN 0 ELSE 1 END AS chg
  FROM sub_events
),
keyed AS (
  SELECT user_id, status, event_date,
    SUM(chg) OVER (PARTITION BY user_id ORDER BY event_date) AS grp
  FROM flagged
)
SELECT user_id, status,
  MIN(event_date) AS period_start,
  MAX(event_date) AS period_end
FROM keyed
GROUP BY user_id, status, grp
ORDER BY user_id, period_start;

이벤트에서 반열린 구간으로

면접에서 자주 놓치는 중요한 점이 있습니다. 이벤트 날짜는 상태가 시작된 시점을 나타내며, 기간은 같은 상태의 마지막 이벤트 날짜가 아니라 다음 상태가 시작될 때 실제로 끝납니다. 따라서 올바른 기간의 끝은 흔히 다음 기간의 시작이며, 반열린 구간 [start, next_start)로 모델링합니다.

통합한 기간에 대해 LEAD로 다음 기간의 시작을 계산하고, 마지막 기간은 끝을 정하지 않은 상태(NULL 또는 ‘현재’)로 둡니다.

WITH periods AS (
  -- output of the previous collapse step
  SELECT user_id, status, period_start FROM collapsed
)
SELECT user_id, status, period_start,
  LEAD(period_start)
    OVER (PARTITION BY user_id ORDER BY period_start)
    AS period_end_exclusive
FROM periods;

연속으로 반복되는 상태 처리

로그에 active, active, active처럼 중간에 변화가 없는 중복 행이 있다면 어떻게 될까요? 반복된 행에서는 변경 플래그가 0이므로 누적 합계가 이 행들을 자동으로 하나의 구간에 계속 포함합니다. 이것이 의도한 동작입니다. 연속으로 같은 상태인 행은 하나의 기간으로 통합됩니다.

이처럼 반복을 자연스럽게 중복 제거할 수 있다는 점은 변경 플래그 방식의 핵심 장점이며, 면접관에게 꼭 설명할 만한 부분입니다.

시간 공백이 기간을 끊어야 하는 경우

때로는 ‘같은 상태’라는 조건만으로는 충분하지 않습니다. 상태가 같더라도 큰 시간 간격이 있으면 기간을 나누어야 할 수 있습니다. 예를 들어 1월에 active였던 사용자가 6개월 동안 활동이 없다가 다시 active가 되었다면 두 개의 기간으로 계산할 수 있습니다.

변경 플래그에 두 번째 조건을 추가하세요. 즉, 상태가 바뀌었거나 이전 이벤트 이후의 시간이 임계값을 초과하면 새 구간을 시작합니다. 이렇게 하면 두 인접성 규칙을 깔끔하게 결합할 수 있습니다.

CASE
  WHEN status = LAG(status)
         OVER (PARTITION BY user_id ORDER BY event_date)
   AND event_date - LAG(event_date)
         OVER (PARTITION BY user_id ORDER BY event_date) <= 31
  THEN 0 ELSE 1
END AS is_change

고유 상태 전환 횟수 세기

자연스러운 후속 질문은 다음과 같습니다. “이 사용자는 상태를 몇 번 전환했나요?” 이는 변경 플래그의 개수에서 첫 번째 플래그를 빼면 됩니다. 첫 번째 플래그는 전환이 아니라 초기 상태를 나타내기 때문입니다.

다르게 말하면 기간의 개수에서 1을 뺀 값입니다. 누적 합계 키가 이미 이 정보를 담고 있으므로, 기간을 만들 때 사용한 동일한 처리 방식으로 답을 구할 수 있습니다.

WITH flagged AS (
  SELECT user_id,
    CASE WHEN status = LAG(status)
           OVER (PARTITION BY user_id ORDER BY event_date)
         THEN 0 ELSE 1 END AS chg
  FROM sub_events
)
SELECT user_id, SUM(chg) - 1 AS status_switches
FROM flagged GROUP BY user_id;

여기서 자체 조인이 불리한 이유

상태 기간을 자체 조인으로 풀려면 각 행을 이웃 행과 짝지어 변화를 찾은 다음 경계를 이어 붙여야 합니다. 이는 오류가 발생하기 쉬운 여러 단계의 작업이며, 기간이 세 개 이상일 때 특히 다루기 어렵습니다.

LAG-플래그-누적합-GROUP BY 처리 흐름은 조인 없이 한 번의 처리로 어떤 개수의 기간이든 처리합니다. 선형적인 단일 처리와 이차적인 자체 조인의 차이를 설명하는 것은 시니어 수준의 사고력을 평가하는 면접관이 정확히 높이 평가하는 부분입니다.

재사용 가능한 템플릿

이 네 절 템플릿을 기억해 두세요. CASE 안의 인접성 검사만 바꾸면 상태 구간 문제 전체를 해결할 수 있습니다.

  1. 플래그: LAG와 CASE로 새 구간을 감지합니다.
  2. 키: 플래그를 누적한 SUM을 파티션별로 계산하고 정렬합니다.
  3. 통합: 파티션 열, 상태, 키를 기준으로 GROUP BY를 수행합니다.
  4. 구간(선택 사항): 반열린 기간의 끝을 구하기 위해 LEAD를 사용합니다.

동일한 뼈대가 연속된 정수, 날짜, 상태에 적용되며, CASE 조건만 바뀝니다.

빠른 확인

상태 구간 그룹화 규칙을 이해했는지 확인합니다.

복습: 상태 및 날짜 구간

이제 공백과 구간 문제의 가장 다양한 변형을 해결할 수 있습니다.

  • 인접성은 이전 행에서 상태가 바뀌지 않았는지로 판단하고, LAG로 플래그를 변경합니다.
  • 변경 플래그를 누적 합산해 기간별 그룹 키를 만듭니다.
  • GROUP BY user_id, status, key로 통합해 기간 범위를 구합니다.
  • 반열린 구간의 끝에는 LEAD를 사용하고, 큰 시간 간격이 있으면 구간이 나뉘도록 플래그를 확장합니다.
  • 동일한 행이 반복되어도 자동으로 통합되며, 상태 전환 횟수도 같은 플래그에서 구할 수 있습니다.
  • 재사용 가능한 하나의 템플릿이 정수, 날짜, 상태에 모두 적용되고 CASE만 바뀝니다.

이로써 SQL 면접에서 시니어 수준을 보여 주는 확실한 신호인 공백과 구간 과정을 마칩니다.

자주 묻는 질문

“날짜와 상태 변화가 있는 아일랜드” 강의는 무료인가요?

네 — “날짜와 상태 변화가 있는 아일랜드” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 SQL Interview Prep 강의 전체를 잠금 해제할 수 있습니다. SQL Interview Prep 강의에는 총 4개의 강의가 포함되어 있습니다.

“날짜와 상태 변화가 있는 아일랜드”에서 뭘 배우나요?

연속된 동일 상태 기간을 그룹화합니다. 구독 상태에서 자주 나오는 문제입니다. 브라우저에서 직접 실행하는 실습 코드로 SQL Interview Prep을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

SQL Interview Prep을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 SQL Interview Prep은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.

“날짜와 상태 변화가 있는 아일랜드” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 SQL Interview Prep 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 SQL Interview Prep 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 갭과 아일랜드 문제 인식하기
  2. 행 번호 차이 기법
  3. 계열에서 누락 구간 찾기
  4. 날짜와 상태 변화가 있는 아일랜드
← SQL Interview Prep(으)로 돌아가기