FIRST_VALUE, LAST_VALUE와 프레임 경계
경계 값을 가져오고 LAST_VALUE 프레임의 함정을 알아봅니다.
FIRST_VALUE, LAST_VALUE와 프레임 경계은(는) CoddyKit의 무료 SQL Interview Prep 강의입니다. 이것은 4개 중 4번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 SQL Interview Prep 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. SQL Interview Prep 강의에는 총 4개의 강의가 포함되어 있습니다.
경계 값 가져오기
면접관은 다음과 같이 묻습니다. “각 행에 해당 그룹의 첫 번째 값과 마지막 값을 함께 표시하세요.” 사용자별 첫 로그인 날짜나, 모든 세부 행 옆에 분할 내 최신 가격을 표시하는 경우를 생각해 보십시오.
사용하는 함수는 FIRST_VALUE와 LAST_VALUE입니다. 단순해 보이지만 LAST_VALUE에는 SQL에서 가장 유명한 윈도 프레임 관련 함정 중 하나가 숨어 있습니다. 이 레슨에서는 두 함수를 안정적으로 사용하는 방법을 다룹니다.
FIRST_VALUE 기본 사항
FIRST_VALUE(col)은 윈도의 첫 행에서 col의 값을 반환하여 모든 행에 연결합니다. 날짜순으로 정렬하면 각 행에 해당 분할에서 가장 이른 값이 표시됩니다.
기본 프레임은 분할의 첫 행에서 시작하므로 FIRST_VALUE는 대개 사람들이 예상하는 대로 동작합니다.
SELECT
user_id,
login_date,
FIRST_VALUE(login_date) OVER (
PARTITION BY user_id
ORDER BY login_date
) AS first_login
FROM logins;기본 윈도우 프레임
핵심은 이것입니다. 윈도우에 ORDER BY를 추가하면 기본 프레임은 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW입니다.
이는 각 행의 윈도우가 파티션 시작부터 현재 행까지만 이어지고 끝까지 이어지지는 않는다는 뜻입니다. FIRST_VALUE에는 영향이 없습니다(첫 행은 항상 범위에 포함되기 때문입니다). 하지만 LAST_VALUE에는 큰 영향을 줍니다.
LAST_VALUE 함정
LAST_VALUE에 ORDER BY만 지정하면 대부분의 지원자는 파티션의 마지막 값을 예상합니다. 하지만 프레임이 현재 행에서 끝나므로 "프레임 안의 마지막 값"은 해당 현재 행 자체의 값일 뿐입니다.
따라서 이 쿼리는 모든 행에서 login_date 자체를 반환하므로 제대로 작동하지 않는 것처럼 보입니다. 이는 윈도우 함수에서 가장 자주 질문받는 함정입니다.
SELECT
user_id,
login_date,
LAST_VALUE(login_date) OVER (
PARTITION BY user_id
ORDER BY login_date
) AS wrong_last_login
FROM logins;전체 프레임으로 LAST_VALUE 수정
해결 방법은 전체 파티션을 포함하도록 프레임을 넓히는 것입니다: ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING.
이제 모든 행의 윈도우가 전체 파티션에 걸치므로 LAST_VALUE가 실제 마지막 값을 반환합니다. 면접에서는 이 수정 방법을 명시적으로 말해 보십시오. 함수 이름만 아는 것이 아니라 프레임을 이해하고 있음을 보여 줍니다.
SELECT
user_id,
login_date,
LAST_VALUE(login_date) OVER (
PARTITION BY user_id
ORDER BY login_date
ROWS BETWEEN UNBOUNDED PRECEDING
AND UNBOUNDED FOLLOWING
) AS last_login
FROM logins;더 쉬운 대안
많은 엔지니어는 프레임을 아예 우회합니다. 마지막 값을 얻으려면 FIRST_VALUE에 반대 순서의 정렬을 사용합니다.
FIRST_VALUE(login_date) OVER (... ORDER BY login_date DESC)는 프레임 절 없이도 가장 최근 날짜를 반환합니다. 깔끔하고 기억하기 쉬운 요령으로 언급하기 좋습니다.
SELECT
user_id,
login_date,
FIRST_VALUE(login_date) OVER (
PARTITION BY user_id
ORDER BY login_date DESC
) AS last_login
FROM logins;프레임에서 ROWS와 RANGE 비교
프레임에는 두 가지 형태가 있습니다. ROWS는 실제 행을 세고, RANGE는 동일한 ORDER BY 값을 기준으로 행을 묶습니다(동률 행).
기본 프레임은 RANGE를 사용하므로 동률인 정렬 값이 하나의 프레임 경계를 공유합니다. LAST_VALUE를 수정할 때는 동률로 인한 예기치 않은 결과를 피하도록 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING을 명시하는 편이 좋습니다.
임의 위치에 사용하는 NTH_VALUE
첫 번째 값과 마지막 값 외에도 NTH_VALUE(col, n)는 프레임 안의 n번째 위치에 있는 값을 가져옵니다. 예를 들어 두 번째로 높은 가격을 가져올 수 있습니다.
이는 LAST_VALUE와 동일한 프레임 규칙을 따릅니다. 따라서 현재 행까지가 아니라 전체 파티션에서 n번째 값을 원한다면 전체 프레임과 함께 사용하십시오.
SELECT
product_id,
price,
NTH_VALUE(price, 2) OVER (
PARTITION BY product_id
ORDER BY price DESC
ROWS BETWEEN UNBOUNDED PRECEDING
AND UNBOUNDED FOLLOWING
) AS second_highest_price
FROM prices;예제: 첫 값과 마지막 값 함께 사용
일반적인 보고서에는 각 거래 옆에 고객의 첫 거래 금액과 마지막 거래 금액을 표시합니다. 두 함수를 함께 사용하되, LAST_VALUE에는 명시적 프레임이 필요하다는 점을 기억하십시오.
이제 모든 행에 전체 파티션의 첫 값과 마지막 값이 들어 있으므로, 차이 계산이나 레이블 지정 단계에 바로 사용할 수 있습니다.
SELECT
customer_id,
txn_date,
amount,
FIRST_VALUE(amount) OVER w AS first_amt,
LAST_VALUE(amount) OVER w AS last_amt
FROM transactions
WINDOW w AS (
PARTITION BY customer_id
ORDER BY txn_date
ROWS BETWEEN UNBOUNDED PRECEDING
AND UNBOUNDED FOLLOWING
);이름 있는 윈도우로 DRY 실천
앞의 쿼리에서는 WINDOW w AS (...) 절을 사용하고 OVER w를 두 번 참조했습니다. 윈도우를 한 번 정의하면 긴 프레임 사양을 반복하지 않아도 되고 두 함수가 서로 어긋나는 것도 방지할 수 있습니다.
대부분의 주요 데이터베이스는 이름 있는 윈도우를 지원합니다. 여러 열이 하나의 윈도우를 공유할 때 이를 사용하는 것은 면접관들이 높이 평가하는 깔끔한 요소입니다.
예제: 첫 값에서 마지막 값까지의 차이
자주 이어지는 질문은 고객의 첫 거래부터 마지막 거래까지의 변화입니다. 각 행에 두 경계값이 있으므로 두 값을 뺀 다음, 필요하면 고객당 한 행만 남도록 중복을 제거합니다.
이는 전체 프레임 수정 방법과 간단한 산술을 결합한 것으로, 면접관이 깔끔하게 완성된 처음부터 끝까지의 답변에서 보고 싶어 하는 유형입니다.
SELECT DISTINCT
customer_id,
LAST_VALUE(amount) OVER w - FIRST_VALUE(amount) OVER w AS first_to_last_delta
FROM transactions
WINDOW w AS (
PARTITION BY customer_id
ORDER BY txn_date
ROWS BETWEEN UNBOUNDED PRECEDING
AND UNBOUNDED FOLLOWING
);간단한 확인
전형적인 LAST_VALUE 함정입니다.
요약
경계값 함수는 프레임에 달려 있습니다:
FIRST_VALUE는 기본 프레임에서 작동하지만LAST_VALUE는 그렇지 않습니다.- 기본 프레임은 현재 행에서 끝나므로
LAST_VALUE는ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING으로 수정하거나, 정렬 순서를 뒤집고FIRST_VALUE를 사용하십시오. NTH_VALUE(col, n)는 임의의 위치에 있는 값을 가져오며, 이름 있는 윈도우는 여러 열의 사양에서 DRY를 유지하게 해 줍니다.
이로써 LAG, LEAD, NTILE 및 경계값 함수 도구 모음이 완성됩니다.
자주 묻는 질문
“FIRST_VALUE, LAST_VALUE와 프레임 경계” 강의는 무료인가요?
네 — “FIRST_VALUE, LAST_VALUE와 프레임 경계” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 SQL Interview Prep 강의 전체를 잠금 해제할 수 있습니다. SQL Interview Prep 강의에는 총 4개의 강의가 포함되어 있습니다.
“FIRST_VALUE, LAST_VALUE와 프레임 경계”에서 뭘 배우나요?
경계 값을 가져오고 LAST_VALUE 프레임의 함정을 알아봅니다. 브라우저에서 직접 실행하는 실습 코드로 SQL Interview Prep을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.
SQL Interview Prep을(를) 시작하는 데 경험이 필요한가요?
사전 경험은 필요하지 않습니다. CoddyKit의 SQL Interview Prep은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 4번째 강의입니다.
“FIRST_VALUE, LAST_VALUE와 프레임 경계” 강의는 얼마나 걸리나요?
대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.
이 SQL Interview Prep 강의에서 코드를 작성하고 실행할 수 있나요?
네. 모든 SQL Interview Prep 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.
이 강의의 모든 강의
- LAG와 LEAD로 인접한 행 다루기
- 기간별 변화
- NTILE로 구간 나누기
- FIRST_VALUE, LAST_VALUE와 프레임 경계