📌 윈도우 함수란?
SUM, AVG, COUNT 등의 집계 함수와 함께 사용 가능 OVER() 절을 사용하여 정의됨 ✅ 예제: 그룹핑을 이용한 연봉 순위 계산
-- 연봉을 높은 순서로 조회
SELECT * FROM salaries ORDER BY salary DESC;
-- playerID 별로 최고 연봉을 가져오기 (GROUP BY 활용)
SELECT playerID, MAX(salary)
FROM salaries
GROUP BY playerID
ORDER BY MAX(salary) DESC;
📌 GROUP BY 문제점:
playerID 별 최고 연봉을 가져오지만, 연도(yearID)와 기타 정보는 소실됨윈도우 함수는 기본적으로 OVER() 절을 사용하며, 다음과 같은 요소를 포함할 수 있다.
| 윈도우 함수 요소 | 설명 |
|---|---|
OVER() | 윈도우 함수의 기본 구조 |
PARTITION BY | 그룹화 기준 (선택 사항) |
ORDER BY | 정렬 기준 (필수) |
ROWS | 데이터 범위 지정 (선택 사항) |
✅ 예제: 연봉 순서에 따른 순위 계산
-- 전체 데이터를 연봉 순서로 나열하고, 순위 표기
SELECT *,
ROW_NUMBER() OVER (ORDER BY salary DESC) AS RowNum, -- 단순 행 번호
RANK() OVER (ORDER BY salary DESC) AS RankNum, -- 순위 (공동 1등 존재 시 2등 없음)
DENSE_RANK() OVER (ORDER BY salary DESC) AS DenseRankNum, -- 순위 (공동 1등 존재 시 다음은 2등)
NTILE(100) OVER (ORDER BY salary DESC) AS PercentileRank -- 백분율 그룹
FROM salaries;
| 함수 | 설명 | 예제 결과 |
|---|---|---|
ROW_NUMBER() | 단순한 행 번호 | 1, 2, 3, 4, 5 |
RANK() | 공동 순위 존재 시 다음 등수 건너뜀 | 1, 1, 3, 4, 5 |
DENSE_RANK() | 공동 순위 존재해도 다음 등수 연속 | 1, 1, 2, 3, 4 |
NTILE(N) | 데이터를 N개 그룹으로 나눔 | 1~100 등급 |
PARTITION BY를 이용한 그룹 내 순위 계산PARTITION BY를 사용하면 특정 그룹 내에서 순위를 계산할 수 있다.
✅ 예제: 플레이어별 연봉 순위 계산
-- playerID 별로 연봉 순위 매기기
SELECT *,
RANK() OVER (PARTITION BY playerID ORDER BY salary DESC) AS RankNum
FROM salaries
ORDER BY playerID;
📌 설명:
PARTITION BY playerID를 사용해 각 플레이어별로 연봉 순위를 별도로 계산 LAG, LEAD)특정 행의 이전 값 또는 다음 값을 가져올 수 있다.
✅ 예제: 플레이어별 연봉 증가/감소 분석
-- LAG(이전 연봉), LEAD(다음 연봉)
SELECT *,
RANK() OVER (PARTITION BY playerID ORDER BY salary DESC) AS RankNum,
LAG(salary) OVER (PARTITION BY playerID ORDER BY salary DESC) AS PrevSalary, -- 이전 연봉
LEAD(salary) OVER (PARTITION BY playerID ORDER BY salary DESC) AS NextSalary -- 다음 연봉
FROM salaries
ORDER BY playerID;
📌 설명:
LAG() : 이전 행의 값 가져오기 LEAD() : 다음 행의 값 가져오기 FIRST_VALUE, LAST_VALUE)특정 그룹 내 가장 첫 번째 또는 마지막 값을 가져온다.
✅ 예제: 각 선수별 최고 연봉과 최저 연봉 조회
-- FIRST_VALUE(최고 연봉), LAST_VALUE(최저 연봉)
SELECT *,
RANK() OVER (PARTITION BY playerID ORDER BY salary DESC) AS RankNum,
FIRST_VALUE(salary) OVER (PARTITION BY playerID ORDER BY salary DESC) AS BestSalary, -- 최고 연봉
LAST_VALUE(salary) OVER (PARTITION BY playerID ORDER BY salary DESC) AS WorstSalary -- 최저 연봉
FROM salaries
ORDER BY playerID;
📌 문제점:
LAST_VALUE() 가 제대로 동작하지 않음 (현재 행부터 최하위 값까지 찾기 때문) ✅ 해결 방법: ROWS BETWEEN UNBOUNDED FOLLOWING 사용
-- 정상적으로 최저 연봉 조회하기
SELECT *,
RANK() OVER (PARTITION BY playerID ORDER BY salary DESC) AS RankNum,
FIRST_VALUE(salary) OVER (PARTITION BY playerID
ORDER BY salary DESC
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS BestSalary,
LAST_VALUE(salary) OVER (PARTITION BY playerID
ORDER BY salary DESC
ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING
) AS WorstSalary
FROM salaries
ORDER BY playerID;
📌 설명:
UNBOUNDED PRECEDING : 첫 번째 행부터 현재 행까지 고려 UNBOUNDED FOLLOWING : 현재 행부터 마지막 행까지 고려