"부서별 평균 급여를 구하면서, 각 직원 행도 그대로 보고 싶다." 이걸 GROUP BY로 하려다 막힌 경험이 한 번쯤 있을 겁니다. GROUP BY는 행을 묶어 줄여버리니까요. 윈도우 함수는 바로 이 문제를 풉니다. 행을 합치지 않고, 각 행 옆에 "그 행이 속한 그룹의 집계값"을 나란히 붙여줍니다. 핵심 키워드는 OVER와 PARTITION BY 두 개뿐입니다.
GROUP BY와 무엇이 다른가
| 구분 | GROUP BY | 윈도우 함수 |
|---|---|---|
| 결과 행 수 | 그룹당 1행으로 줄어듦 | 원본 행 수 그대로 유지 |
| 원본 컬럼 | 집계/그룹 키만 남음 | 모든 컬럼 그대로 + 집계값 추가 |
| 용도 | 요약 통계 | 행별 비교, 순위, 누적 |
쉽게 말해 GROUP BY는 "부서별 한 줄 요약표"를, 윈도우 함수는 "원래 명단 옆에 부서 평균을 적어둔 표"를 만듭니다.
OVER와 PARTITION BY 읽는 법
윈도우 함수의 뼈대는 함수() OVER (PARTITION BY 기준) 입니다. OVER는 "이 함수를 윈도우(행 묶음) 위에서 계산하라"는 뜻이고, PARTITION BY는 "어떤 기준으로 묶을지"를 정합니다.
SELECT
name,
dept,
salary,
AVG(salary) OVER (PARTITION BY dept) AS dept_avg
FROM employee;
이 쿼리는 직원 명단을 한 줄도 줄이지 않습니다. 대신 각 행 옆에 그 직원이 속한 부서의 평균 급여(dept_avg)를 붙입니다. 영업팀 직원 행에는 영업팀 평균이, 개발팀 행에는 개발팀 평균이 자동으로 들어갑니다. PARTITION BY를 빼면 전체 직원을 한 묶음으로 보고 회사 전체 평균이 모든 행에 붙습니다.
순위 매기기: ORDER BY 추가
OVER 안에 ORDER BY를 넣으면 순위·누적 계산이 됩니다.
SELECT
name,
dept,
salary,
RANK() OVER (PARTITION BY dept ORDER BY salary DESC) AS rank_in_dept
FROM employee;
부서별로 급여 높은 순서대로 등수를 매깁니다. RANK()는 동점이면 같은 등수를 주고 다음 등수를 건너뜁니다(1,1,3). 건너뛰지 않으려면 DENSE_RANK(), 동점 없이 무조건 일련번호를 원하면 ROW_NUMBER()를 씁니다.
| 함수 | 동점 처리 | 결과 예 |
|---|---|---|
| ROW_NUMBER() | 동점도 다른 번호 | 1, 2, 3, 4 |
| RANK() | 동점 같은 등수, 다음 건너뜀 | 1, 1, 3, 4 |
| DENSE_RANK() | 동점 같은 등수, 안 건너뜀 | 1, 1, 2, 3 |
"부서별 급여 상위 3명만" 같은 요구는 이 순위를 서브쿼리로 감싸 rank_in_dept <= 3 으로 거르면 됩니다.
요점 정리
- 윈도우 함수는 행을 줄이지 않고, 각 행 옆에 그룹 집계값을 붙인다.
OVER가 "윈도우 위에서 계산",PARTITION BY가 "묶는 기준"이다.OVER에ORDER BY를 넣으면RANK·ROW_NUMBER등 순위·누적 계산이 된다.
PARTITION BY와 ORDER BY를 바꿔가며 결과가 어떻게 달라지는지 직접 실행해 보는 실습은 데이터베이스 트랙에서 회원가입 없이 무료로 할 수 있습니다.