0Pricing
Coding Interview Prep · 강의

키별 최신 행 유지하기

키별로 파티션을 나누고 날짜순으로 정렬해 ‘고객별 가장 최근 레코드’를 찾는 패턴을 알아봅니다.

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

키별 최신 행 문제

“각 고객의 가장 최근 주문을 반환하십시오.” “모든 기기의 최신 상태를 가져오십시오.” 이 키별 최신 행 문제는 실제 분석 업무에서 매우 자주 등장하므로 SQL 면접에서 가장 빈번하게 출제되는 작업 중 하나입니다.

이는 그룹별 최상위 1개를 찾는 문제의 특수한 형태입니다. 키를 기준으로 파티션을 나누고, 타임스탬프를 내림차순으로 정렬한 뒤 첫 번째 행을 남깁니다. 이 레슨에서는 이 패턴과 대안을 집중적으로 익힙니다.

MAX만으로는 부족한 이유

처음 떠올리기 쉬운 답은 고객별로 그룹을 묶어 MAX(order_date)를 구하는 것입니다. 이렇게 하면 가장 최근 날짜는 얻지만, 해당 주문의 나머지 열, 주문 id, 금액 또는 상태는 얻을 수 없습니다.

면접관이 가장 최근 행 전체를 원한다면 MAX와 GROUP BY를 함께 사용한 뒤 키와 최댓값 날짜를 기준으로 테이블에 다시 조인해야 합니다. 이 방식은 장황하고 동률에서 문제가 생길 수 있습니다. 윈도 함수가 더 깔끔합니다.

-- Gives the date, not the full row
SELECT customer_id, MAX(order_date) AS last_order
FROM orders
GROUP BY customer_id;

ROW_NUMBER 패턴

키를 기준으로 파티션을 나누고 타임스탬프를 내림차순으로 정렬하면 최신 행에 rn = 1이 지정됩니다. 이 행들만 남기면 키마다 가장 최근 기록 전체를 얻을 수 있습니다.

가장 먼저 선택할 대표 답변입니다. 타임스탬프가 동률이어도 키마다 정확히 한 행을 반환하며, 보통 “최신 행”이라는 표현은 이를 의미합니다.

WITH ranked AS (
  SELECT *,
    ROW_NUMBER() OVER (
      PARTITION BY customer_id
      ORDER BY order_date DESC
    ) AS rn
  FROM orders
)
SELECT customer_id, order_id, order_date, amount
FROM ranked
WHERE rn = 1;

타임스탬프 동률 해소

같은 고객의 두 주문이 동일한 order_date를 가질 수 있습니다. 같은 날이거나 타임스탬프가 완전히 같을 때가 그렇습니다. 동률 해소 기준이 없으면 어느 행이 rn = 1이 될지 임의로 정해지며 실행마다 달라질 수 있습니다.

order_id DESC와 같은 고유한 보조 키를 추가하여 최신 행을 결정적으로 선택하십시오. 면접관은 지원자가 이 예외 상황을 인지했는지 특히 확인합니다.

ROW_NUMBER() OVER (
  PARTITION BY customer_id
  ORDER BY order_date DESC, order_id DESC
) AS rn

최신 행과 모든 동률 행

타임스탬프가 동률일 때 “최신”이 무엇을 의미하는지 결정하십시오.

  • 키마다 정확히 하나의 행을 원한다면 → 동률 해소 기준을 추가한 ROW_NUMBER를 사용하십시오.
  • 최댓값 타임스탬프를 공유하는 모든 행을 원한다면 → RANK() = 1을 사용하십시오. 동률인 최신 행을 모두 반환합니다.

이 명확화 질문을 하면 단순히 구문만 아는 것이 아니라 의미를 이해하고 있음을 보여 줄 수 있습니다.

WITH ranked AS (
  SELECT *,
    RANK() OVER (
      PARTITION BY customer_id ORDER BY order_date DESC
    ) AS rnk
  FROM orders
)
SELECT * FROM ranked WHERE rnk = 1;

상관 하위 질의 대안

윈도 함수가 보편화되기 전에는 상관 하위 질의를 사용해 키별 최신 행을 구했습니다. 같은 키를 가진 다른 행 중 더 큰 날짜를 가진 행이 없을 때만 해당 행을 남기는 방식입니다.

작동하기는 하지만 행마다 내부 질의를 실행하므로 큰 테이블에서는 더 느리고, 동률을 처리하기도 까다롭습니다. 다양한 접근을 알고 있음을 보여 주기 위해 언급할 수는 있지만, 성능을 위해서는 윈도 함수 답변을 우선하십시오.

SELECT o.*
FROM orders o
WHERE o.order_date = (
  SELECT MAX(o2.order_date)
  FROM orders o2
  WHERE o2.customer_id = o.customer_id
);

PostgreSQL DISTINCT ON 단축법

PostgreSQL은 간결한 관용구를 제공합니다. DISTINCT ON (key)는 ORDER BY에 따라 키마다 첫 번째 행을 남깁니다. ORDER BY는 먼저 같은 키 열로 시작한 다음 동률 해소 기준 또는 타임스탬프를 지정해야 합니다.

PostgreSQL에서는 우아하고 빠르지만 이식성이 없습니다. 특정 SQL 문법 체계에서만 가능한 추가 선택지로 언급하되, 이식성이 필요한 기본 답변으로는 ROW_NUMBER를 유지하십시오.

SELECT DISTINCT ON (customer_id)
  customer_id, order_id, order_date, amount
FROM orders
ORDER BY customer_id, order_date DESC, order_id DESC;

조건이 있는 최신 행

실제 문제에는 필터가 추가됩니다. 예를 들어 “고객별 가장 최근의 완료된 주문”을 찾는 경우입니다. 순위를 매기기 전에 필터를 적용하여 조건을 만족하는 행에만 번호를 지정하십시오.

조건을 내부 질의의 WHERE에 넣으십시오. 내부 질의가 윈도 함수보다 먼저 실행되기 때문입니다. 그런 다음 외부 질의에서 rn = 1을 선택하십시오. 순위를 매긴 후 필터링하면 잘못된 행이 반환됩니다.

WITH ranked AS (
  SELECT *,
    ROW_NUMBER() OVER (
      PARTITION BY customer_id ORDER BY order_date DESC, order_id DESC
    ) AS rn
  FROM orders
  WHERE status = 'completed'
)
SELECT * FROM ranked WHERE rn = 1;

예제: 최신 기기 상태

status_log 테이블에는 device_id, status, logged_at이 기록되어 있습니다. 각 기기의 현재 상태를 가져오려면 device_id를 기준으로 파티션을 나누고, logged_at DESC로 정렬한 뒤 rn = 1을 남기십시오.

이는 추가만 가능한 이벤트 기록에서 여러 개체의 “현재 상태”를 보여 주는 대시보드의 핵심 원리입니다. 같은 방법으로 최신 가격, 최신 위치 및 최신 버전을 조회할 수 있습니다.

WITH latest AS (
  SELECT device_id, status, logged_at,
    ROW_NUMBER() OVER (
      PARTITION BY device_id ORDER BY logged_at DESC
    ) AS rn
  FROM status_log
)
SELECT device_id, status, logged_at
FROM latest
WHERE rn = 1;

성능 관련 참고 사항

숙련자로 인정받는 데 도움이 되는 설명은 다음과 같습니다.

  • (customer_id, order_date DESC)에 인덱스를 만들면 엔진이 키별 최신 행을 효율적으로 읽을 수 있습니다.
  • 윈도 방식은 테이블을 한 번만 훑지만, 상관 하위 질의는 그렇지 않습니다.
  • PostgreSQL의 DISTINCT ON은 같은 인덱스를 사용할 수 있어 단일 테이블을 조회하는 방법 중 가장 빠른 경우가 많습니다.
  • 추가 작업이 많은 이벤트 기록이라면 증분 방식으로 갱신하는 구체화된 “최신” 테이블을 고려하십시오.

흔한 실수

다음 사항을 주의하십시오.

  • MAX(date)를 사용하고 전체 행이 아니라 날짜만 반환하는 경우
  • 동률 해소 기준을 빠뜨려 날짜가 같을 때 결과가 비결정적으로 나오는 경우
  • 순위를 매긴 후에 조건을 필터링하여 원래 제외했어야 할 행을 선택하는 경우
  • “최신 행 하나”(ROW_NUMBER)와 “동률인 최신 행 모두”(RANK)를 혼동하는 경우

빠른 확인

올바른 키별 최신 행 질의를 선택하십시오.

복습: 키별 최신 행

패턴: PARTITION BY 키, ORDER BY 타임스탬프 DESC (고유한 동률 해소 기준 추가), 행 번호가 1인 항목 유지

  • MAX(date)는 전체 행이 아니라 날짜를 반환합니다.
  • 결과가 결정적이 되도록 항상 동률 해소 기준을 추가하십시오.
  • 최신 타임스탬프에서 동률인 모든 행을 원한다면 RANK() = 1을 사용하십시오.
  • 조건 필터는 순위를 매기기 전인 내부 질의에 있어야 합니다.
  • PostgreSQL의 DISTINCT ON은 간결하고 빠른 문법 체계별 대안입니다.

자주 묻는 질문

“키별 최신 행 유지하기” 강의는 무료인가요?

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

“키별 최신 행 유지하기”에서 뭘 배우나요?

키별로 파티션을 나누고 날짜순으로 정렬해 ‘고객별 가장 최근 레코드’를 찾는 패턴을 알아봅니다. 브라우저에서 직접 실행하는 실습 코드로 Coding Interview Prep을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

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

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

“키별 최신 행 유지하기” 강의는 얼마나 걸리나요?

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

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

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

이 강의의 모든 강의

  1. ROW_NUMBER로 그룹별 상위 N개 행 찾기
  2. 상위 N개 결과에서 동점 처리하기
  3. 안전하게 행 중복 제거하기
  4. 키별 최신 행 유지하기
← Coding Interview Prep(으)로 돌아가기