데이터베이스 용어 사전
SQLOVER · PARTITION BY · ROW_NUMBER · RANK

윈도우 함수

그룹으로 접지 않고 각 행에서 옆을 보게 해 주는 함수. 순위·누적합·이전 값 비교에 쓴다.

행을 그룹으로 접지 않고, 각 행마다 정해진 범위(윈도우)를 보며 계산하는 함수.

GROUP BY와 무엇이 다른가

GROUP BY여러 행을 한 행으로 '접는다'→ 원래 행 정보가 사라진다
OVER행은 그대로 두고 옆을 '본다'→ 원래 행 + 계산 결과를 함께 얻는다
-- GROUP BY: 부서별 평균만 남는다
SELECT dept, avg(salary) FROM emp GROUP BY dept;

-- OVER: 각 사원 행에 그 부서 평균이 따라붙는다
SELECT name, dept, salary, avg(salary) OVER (PARTITION BY dept) AS dept_avg
  FROM emp;
-- 김철수 | 개발 | 5000 | 5200
-- 이영희 | 개발 | 5400 | 5200      ← 개인 정보를 잃지 않는다

구조

함수() OVER (
  PARTITION BY 그룹기준     -- 어떻게 나눌까 (생략하면 전체가 한 덩어리)
  ORDER BY 정렬기준         -- 어떤 순서로 볼까
  ROWS BETWEEN ... AND ...  -- 어디까지 볼까 (프레임)
)

순위 세 형제 — 동점 처리가 다르다

SELECT name, score,
       ROW_NUMBER() OVER (ORDER BY score DESC) AS rn,
       RANK()       OVER (ORDER BY score DESC) AS rk,
       DENSE_RANK() OVER (ORDER BY score DESC) AS dr
  FROM student;

-- score 100, 100, 90 일 때
-- rn: 1, 2, 3     무조건 순번 (동점도 임의로 가른다)
-- rk: 1, 1, 3     동점은 같은 등수, 다음은 건너뛴다
-- dr: 1, 1, 2     동점은 같은 등수, 다음이 이어진다

그룹별 상위 N — 가장 흔한 용도

-- 부서별 연봉 상위 3명
SELECT * FROM (
  SELECT name, dept, salary,
         ROW_NUMBER() OVER (PARTITION BY dept ORDER BY salary DESC) AS rn
    FROM emp
) t WHERE rn <= 3;

윈도우 함수는 WHERE에서 쓸 수 없다 — 실행 순서상 WHERE가 먼저 처리되기 때문이다. 그래서 서브쿼리나 CTE로 한 겹 감싼다.

누적과 이전 값 비교

-- 누적 매출
SELECT d, amount,
       sum(amount) OVER (ORDER BY d ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) AS cum
  FROM daily_sales;

-- 전일 대비 증감 — 이전 행의 값을 당겨 온다
SELECT d, amount,
       amount - LAG(amount) OVER (ORDER BY d) AS diff
  FROM daily_sales;

LAG(이전 행)·LEAD(다음 행)는 자기 조인 없이 시계열 비교를 하게 해 준다. 예전에는 같은 테이블을 하루 어긋나게 조인해야 했던 일이다.

지원 현황

  • PostgreSQL — 8.4 부터 (오래됐다)
  • MySQL — 8.0 부터 — 5.7 이하에서는 변수 트릭으로 흉내 내야 했다

면접 함정

  • "윈도우 함수는 느리다" → 대안(자기 조인·상관 서브쿼리)이 대개 더 느리다. 정렬 비용은 인덱스로 줄인다.
  • "RANK와 ROW_NUMBER는 같다" → 동점 처리가 다르다. 페이지네이션에는 유일성이 보장되는 ROW_NUMBER를 쓴다.

함께 보면 좋은 용어

노트에서 맥락과 함께 보기 — SQL 쿼리문 — SELECT·조인·서브쿼리·집계·윈도우·CTE