Coding Interview Prep · 강의

행 번호 차이 기법

ROW_NUMBER를 계열에서 빼 연속된 값을 아일랜드로 그룹화합니다.

레슨 2/413개 단계

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

가장 우아한 구간 키

행 번호 차이 기법은 연속된 정수 또는 날짜로 이루어진 구간에서 면접관이 가장 보고 싶어 하는 기법입니다. 한 번의 뺄셈으로 그룹 키를 만들므로 LAG나 누적 합계가 필요하지 않습니다.

핵심 아이디어는 값 자체에서 ROW_NUMBER를 빼는 것입니다. 연속된 값의 어느 구간에서든 값과 행 번호는 매 단계 정확히 1씩 증가하므로, 두 값의 차이는 구간 전체에서 일정합니다. 이 일정한 값이 구간 키입니다.

차이가 일정하게 유지되는 이유

연속 구간에서 서로 인접한 두 행을 생각해 보십시오. 한 행에서 다음 행으로 이동하면 값이 1 증가하고 행 번호도 1 증가합니다. 두 값을 빼면 +1이 서로 상쇄되므로 value - row_number는 변하지 않습니다.

하지만 간격이 생기는 순간 값은 1보다 크게 뛰고, 행 번호는 여전히 1만큼만 증가합니다. 따라서 차이가 새로운 일정한 값으로 바뀝니다. 바로 이 변화가 한 구간과 다음 구간을 나눕니다.

데이터에 적용해 보기

로그인 날짜 1, 2, 3, 7, 8, 10을 다시 살펴보겠습니다. 행 번호와 차이를 나란히 놓으면 다음과 같습니다.

  • 일수 1, 행 번호 1, 차이 0
  • 일수 2, 행 번호 2, 차이 0
  • 일수 3, 행 번호 3, 차이 0
  • 일수 7, 행 번호 4, 차이 3
  • 일수 8, 행 번호 5, 차이 3
  • 일수 10, 행 번호 6, 차이 4

차이값(0,0,0,3,3,4)은 행을 세 구간으로 정확히 나눕니다. 차이가 같으면 같은 구간입니다.

SELECT
  day_no,
  ROW_NUMBER() OVER (ORDER BY day_no) AS rn,
  day_no - ROW_NUMBER() OVER (ORDER BY day_no) AS grp
FROM logins
ORDER BY day_no;

구간으로 합치기

차이를 그룹 키로 사용하면 최종 쿼리는 표준적인 통합 쿼리가 됩니다. 차이를 CTE로 감싼 다음 이를 기준으로 GROUP BY를 적용하십시오.

이 쿼리는 이전과 동일한 세 구간을 반환하지만, LAG와 누적 합계를 함께 사용하는 방식보다 SQL이 짧고 명확합니다. 정수 또는 일정한 간격으로 증가하는 순열에서는 이 방법을 가장 먼저 고려하십시오.

WITH keyed AS (
  SELECT
    day_no,
    day_no - ROW_NUMBER() OVER (ORDER BY day_no) AS grp
  FROM logins
)
SELECT
  MIN(day_no) AS start_day,
  MAX(day_no) AS end_day,
  COUNT(*)    AS length
FROM keyed
GROUP BY grp
ORDER BY start_day;

주의할 점: 값은 1씩 증가해야 합니다

단순한 차이 기법은 수열이 매 단계마다 정확히 1씩 증가한다고 가정합니다. 이는 빈틈없는 정수와 연속된 달력 날짜에는 맞지만, 값이 다른 일정한 간격으로 증가하거나 중복값이 있으면 제대로 작동하지 않습니다.

  • 2, 4, 6, 8과 같은 짝수는 값에서 행 번호를 뺀 결과를 사용하면 누락 구간처럼 보입니다.
  • 중복값이 있으면 값은 그대로인데 행 번호만 계속 증가하므로 정렬이 어긋납니다.

이러한 한계와 이를 수정하는 방법을 알아야 암기한 요령을 넘어 실제로 이해했다고 할 수 있습니다.

일정한 간격 수열 수정하기

값이 1이 아니라 알려진 상수 k만큼씩 증가한다면 먼저 정규화해야 합니다. 값을 k로 나누거나 정수에는 value / k를 사용하여 각 단계가 다시 1씩 증가하도록 만든 다음 행 번호를 뺍니다.

예를 들어 2씩 증가하는 짝수에는 day_no / 2 - ROW_NUMBER()를 사용합니다. 이제 정규화된 값은 연속된 각 항목에서 1씩 증가하므로, 일정한 차이라는 특성이 다시 성립합니다.

SELECT
  val,
  (val / 2) - ROW_NUMBER() OVER (ORDER BY val) AS grp
FROM even_series
ORDER BY val;

날짜에 적용하기

날짜는 이 기법이 실제로 가장 자주 적용되는 대상입니다. 달력 날짜는 행 번호에서 직접 뺄 수 없으므로 먼저 날짜를 일수로 변환해야 합니다. Postgres에서는 고정된 기준 날짜를 빼서 정수로 된 일수를 얻은 다음 같은 기법을 적용합니다.

연속된 달력 날짜의 차이는 1이므로, 일수와 행 번호의 차이는 연속 구간 안에서 다시 일정해집니다.

WITH keyed AS (
  SELECT
    login_date,
    (login_date - DATE '2000-01-01')
      - ROW_NUMBER() OVER (ORDER BY login_date) AS grp
  FROM daily_logins
)
SELECT MIN(login_date) AS start_date,
       MAX(login_date) AS end_date,
       COUNT(*)        AS days_in_run
FROM keyed GROUP BY grp ORDER BY start_date;

데이터베이스별 날짜 차이 계산

날짜를 정수로 변환하는 단계는 데이터베이스 엔진마다 다르므로, 여러 데이터베이스 방언을 알고 있으면 면접에서 좋은 평가를 받을 수 있습니다.

  • 포스트그레스: 날짜 리터럴을 뺍니다. login_date - DATE '2000-01-01'은 정수를 반환합니다.
  • MySQL: DATEDIFF(login_date, '2000-01-01')을 사용합니다.
  • 에스큐엘 서버: DATEDIFF(day, '2000-01-01', login_date)를 사용합니다.

일부 엔진에서는 더 간결한 방법도 있습니다. 날짜에서 ROW_NUMBER일을 INTERVAL 연산으로 직접 뺀 다음, 그 결과인 기준 날짜로 GROUP BY하면 됩니다.

SELECT
  login_date,
  login_date - (ROW_NUMBER() OVER (ORDER BY login_date)
               * INTERVAL '1 day') AS grp_date
FROM daily_logins;

그룹별 PARTITION 추가하기

사용자별 연속 구간을 구하려면 그룹 열을 기준으로 행 번호를 PARTITION해야 합니다. 중요한 점은 그룹 키에 PARTITION 열도 포함해야 한다는 것입니다. 서로 다른 사용자가 우연히 같은 차이값을 만들 수 있기 때문입니다.

따라서 user_id와 계산된 차이값을 모두 GROUP BY해야 합니다. 최종 GROUP BY에서 user_id를 빠뜨리는 것은 면접관이 자주 찾아내는 미묘한 버그입니다.

WITH keyed AS (
  SELECT user_id, day_no,
    day_no - ROW_NUMBER()
      OVER (PARTITION BY user_id ORDER BY day_no) AS grp
  FROM logins
)
SELECT user_id, MIN(day_no) AS start_day,
       MAX(day_no) AS end_day, COUNT(*) AS len
FROM keyed
GROUP BY user_id, grp
ORDER BY user_id, start_day;

차이 기법과 LAG: 무엇을 사용할까요

이제 두 가지 확실한 기법을 사용할 수 있습니다. 상황에 맞게 선택하십시오.

  • 행 번호 차이: 일정한 간격으로 증가하는 값의 연속 구간, 즉 빈틈없는 정수나 연속된 날짜를 다룰 때 가장 짧고 깔끔합니다. 인접함을 ‘일정한 값만큼 차이 나는 것’으로 정의할 때 첫 번째로 고려할 방법입니다.
  • LAG와 누적합: 인접함이 일정한 숫자 간격이 아닐 때 더 유연합니다. 예를 들어 ‘이전 행과 같은 상태’나 불규칙한 사용자 지정 규칙을 다룰 때 적합합니다.

면접에서는 어떤 방법을 선택했는지와 그 이유를 설명하십시오. 문법보다 그 이유가 더 깊은 이해를 보여 줍니다.

중복에 대비해 안전하게 처리하기

값이 반복될 수 있는데도 연속된 각 구간마다 하나의 아일랜드를 만들고 싶다면, 먼저 DISTINCT나 그룹화 단계로 중복을 제거하여 행 번호와 값이 일대일로 대응하도록 하십시오. 또는 ROW_NUMBER 대신 DENSE_RANK를 사용하여 같은 값을 같은 순위로 처리할 수도 있습니다.

항상 면접관에게 중복이 발생할 수 있는지 물어보십시오. 중복값이 연속 구간을 늘려야 하는지, 아니면 구간 안에서 무시해야 하는지에 따라 적절한 대응이 달라집니다.

WITH d AS (SELECT DISTINCT day_no FROM logins)
SELECT day_no,
  day_no - ROW_NUMBER() OVER (ORDER BY day_no) AS grp
FROM d;

빠른 확인

이 기법이 왜 작동하는지 확실히 이해했는지 확인하십시오.

복습: 차이 기법

이제 가장 깔끔한 연속 구간 키를 익혔습니다.

  • 핵심 공식: value - ROW_NUMBER() OVER (ORDER BY value)는 연속된 각 구간에서 일정합니다.
  • 그 차이값으로 GROUP BY하여 시작값, 끝값, 길이를 구합니다.
  • 일정한 간격 수열에서는 먼저 정규화합니다. 즉, 증가 간격으로 나눕니다.
  • 날짜에서는 해당 데이터베이스 방언의 차이 함수를 사용하여 정수 일수로 변환합니다.
  • 그룹별로 처리할 때는 행 번호를 PARTITION BY하고 최종 GROUP BY에 그룹 열을 포함합니다.
  • DISTINCT나 DENSE_RANK로 중복에 대비합니다.

다음에는 연속 구간에서 빈 공간으로 초점을 옮겨 누락 구간을 찾아보겠습니다.

무료로 시작

AI 튜터와 함께 Coding Interview Prep을(를) 배우세요 — 무료

브라우저에서 실제 코드를 작성하고 실행하며, 24/7 AI 튜터로부터 즉각적인 도움을 받고, 웹이나 앱에서 중단한 부분부터 계속 학습하세요.

코스
90
레슨
360

자주 묻는 질문

“행 번호 차이 기법” 강의는 무료인가요?

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

“행 번호 차이 기법”에서 뭘 배우나요?

ROW_NUMBER를 계열에서 빼 연속된 값을 아일랜드로 그룹화합니다. 브라우저에서 직접 실행하는 실습 코드로 Coding Interview Prep을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

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

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

“행 번호 차이 기법” 강의는 얼마나 걸리나요?

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

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

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

이 강의의 모든 강의

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