436. 윈도우 함수 OVER (PARTITION BY)
⚠️ 이 문서는 "각 부서별로 급여가 1등인 사람을 찾되, 원본 직원 데이터 1,000줄은 그대로 다 보여줘!"라는 까다로운 요구사항을, **원본 행(Row)을 뭉쳐버리지 않으면서(GROUP BY의 한계 극복) 마치 돋보기를 대고 부분적인 통계만 계산해 내는 '윈도우 함수'**를 다룹니다.
핵심 인사이트 (3줄 요약)
- 본질: 기존의
GROUP BY가 여러 줄의 데이터를 1줄로 확 뭉쳐서 퉁쳐버린다면, 윈도우 함수는 원본 데이터의 줄 수를 100% 그대로 유지한 채 그 옆에 통계값(합계, 순위 등)을 살짝 끼워 넣어주는 함수다.- 문법: 윈도우 함수는 뒤에 반드시
OVER ()라는 키워드를 달고 다닌다. 이 괄호 안에서 데이터를 어떻게 자르고 정렬할지(PARTITION BY,ORDER BY)를 결정한다.- 가치: 이 함수가 없었다면 백엔드 개발자는 DB에서 데이터를 다 긁어와 자바나 파이썬에서 이중
for문을 돌려가며 순위를 매기는 엄청난 노가다를 해야 했을 것이다.
Ⅰ. 개요: 뭉치지 말고 알려줘 (Context & Necessity)
"우리 회사 직원들 목록이랑, 각 직원이 속한 부서의 평균 월급을 같이 보여줘."
초보 개발자의 접근 (GROUP BY 사용):
SELECT 이름, 부서, AVG(월급) FROM 직원 GROUP BY 부서; -- 에러 발생!
GROUP BY를 쓰면 부서별로 데이터가 딱 1줄씩으로 찌부러진다(뭉쳐진다).
따라서 개별 직원의 '이름'은 다 사라져버려서 화면에 뿌려줄 수가 없다.
고수 개발자의 접근 (윈도우 함수 사용):
SELECT 이름, 부서, 월급,
AVG(월급) OVER (PARTITION BY 부서) AS 부서평균
FROM 직원;
직원이 100명이라면 결과도 정확히 100줄이 나온다. 그리고 각 직원의 줄 끝부분에, 그 직원이 속한 부서의 평균 월급 숫자가 예쁘게 따라붙는다.
📢 섹션 요약 비유:
GROUP BY가 **'반 평균 성적표(반당 1장)'**를 뽑아내는 것이라면, 윈도우 함수는 학생 30명의 **'개인 성적표(총 30장)'**를 나눠주면서, 그 성적표 구석에 '우리 반 평균은 80점'이라고 친절하게 같이 적어주는 마법입니다.
Ⅱ. OVER 절의 핵심 구조 ★
윈도우 함수는 무조건 OVER를 뒤집어써야 작동한다. 그 안에는 3가지 옵션이 들어갈 수 있다.
1. PARTITION BY (구역 나누기)
- 역할: "어떤 그룹을 묶어서 계산할래?"
- 작동:
GROUP BY와 느낌이 비슷하다.PARTITION BY 부서라고 하면 부서별로 유리 칸막이(Window)를 친다.
2. ORDER BY (정렬하기)
- 역할: "그 칸막이 안에서 어떤 순서로 계산할래?"
- 작동: 누적 합계나 순위(
RANK())를 구할 때 무조건 필요하다.ORDER BY 월급 DESC라고 하면 1등부터 순서대로 번호를 매긴다.
3. ROWS / RANGE (창문 크기 조절하기)
- 역할: "칸막이 안에서도 어디서부터 어디까지만 계산할래?"
- 작동: 주식 차트에서 '최근 3일 이동 평균선'을 구할 때 쓴다. (예:
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW)
Ⅲ. 대표적인 윈도우 함수들
이 함수들은 오직 OVER와 함께 쓸 때만 의미가 있다.
- 순위 함수:
RANK(),DENSE_RANK(),ROW_NUMBER()(437번 문서 참조) - 집계 함수:
SUM(),AVG(),MAX(),MIN(),COUNT() - 행 순서 함수:
LEAD(): "내 뒷사람의 월급은 얼마지?"LAG(): "내 앞사람의 월급은 얼마지?" (전월 대비 매출 증감률 구할 때 최고!)
┌──────────────────────────────────────────────────────────────┐
│ 윈도우 함수(PARTITION BY)의 작동 원리 시각화 │
├──────────────────────────────────────────────────────────────┤
│ │
│ [ 👨💼 원본 테이블 (6명) ] │
│ 영업팀: 철수(300), 영희(400) │
│ 개발팀: 민수(500), 수진(600), 길동(700) │
│ 인사팀: 철민(200) │
│ │
│ [ 🪟 윈도우 함수 실행: SUM(월급) OVER (PARTITION BY 팀) ] │
│ │
│ 이름 │ 팀 │ 월급 │ 🌟 팀_총월급(윈도우 결과) │
│ ────┼──────┼──────┼──────────────────── │
│ 철수 │ 영업 │ 300 │ 700 ◀── (영업팀 칸막이 안에서 300+400 계산됨)│
│ 영희 │ 영업 │ 400 │ 700 ◀── (원래 데이터 행수는 그대로 유지됨!) │
│ ────┼──────┼──────┼──────────────────── │
│ 민수 │ 개발 │ 500 │ 1800 ◀── (개발팀 칸막이 계산) │
│ 수진 │ 개발 │ 600 │ 1800 │
│ 길동 │ 개발 │ 700 │ 1800 │
│ ────┼──────┼──────┼──────────────────── │
│ 철민 │ 인사 │ 200 │ 200 ◀── (인사팀 칸막이 계산) │
└──────────────────────────────────────────────────────────────┘
Ⅳ. 결론
"데이터를 접지 않고도 전체를 내려다보는 눈."
윈도우 함수가 RDBMS에 도입된 이후, 백엔드 개발자들의 통계 쿼리 작성 시간은 절반으로 줄어들었다. 예전에는 이런 결과를 얻기 위해 서브쿼리(Subquery)를 만들어 GROUP BY를 돌리고 그걸 다시 원래 테이블과 조인(JOIN)하는 끔찍한 코드를 짜야 했다. 윈도우 함수는 단순히 코드를 줄여주는 것을 넘어, 디스크를 여러 번 읽어야 하는 조인 연산을 획기적으로 줄여주어 쿼리 성능(Performance) 최적화에도 막대한 기여를 하는 현대 SQL의 꽃이다.
📌 관련 개념 맵
- 관련 문법:
GROUP BY(뭉치기), 서브쿼리 (434번 문서) - 심화 함수:
RANK/DENSE_RANK(437번 문서) - 주의점: 윈도우 함수는
WHERE절에서 쓸 수 없다. 반드시SELECT나ORDER BY절에서만 써야 한다. (조건으로 쓰려면 인라인 뷰로 한 번 감싸야 함)
👶 어린이를 위한 3줄 비유 설명
GROUP BY는 30명 반 친구들 사진을 다 버리고 '우리 반 단체 사진 1장'만 딱 찍는 거예요. 내 얼굴은 안 보이죠.- 윈도우 함수는 30명 친구들의 '개인 증명사진 30장'을 그대로 살려두는 거예요.
- 대신 각자의 증명사진 여백에다가 "우리 반 평균 키는 140cm"라는 추가 정보(도장)를 친절하게 다 찍어주는 거랍니다!