🔥 1. 윈도우 함수(Windows Function)란?

📌 윈도우 함수란?

  • 행들의 서브 집합을 대상으로, 각 행별로 특정 연산을 수행하여 단일 값(스칼라 값)을 반환하는 함수
  • GROUP BY와 유사하지만, 데이터가 사라지지 않고 개별 행을 유지한 채 연산 가능
  • 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)와 기타 정보는 소실됨
  • 이를 해결하기 위해 윈도우 함수 사용

🔥 2. 윈도우 함수 기본 문법

윈도우 함수는 기본적으로 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 등급

🔥 3. 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를 사용해 각 플레이어별로 연봉 순위를 별도로 계산
  • 연도별로 각 선수의 연봉 순위를 개별적으로 평가 가능

🔥 4. 이전/다음 값 비교 (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() : 다음 행의 값 가져오기
  • 연봉이 상승했는지, 하락했는지 분석 가능

🔥 5. 첫 번째/마지막 값 가져오기 (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 : 현재 행부터 마지막 행까지 고려
  • 이를 통해 정확한 최고/최저 연봉 계산 가능

profile
李家네_공부방

0개의 댓글