[SQLD 16화] 윈도우 함수 기초와 OVER 절을 활용한 실시간 누적 합계(Cum Sum) 실무 가공 테크닉 (SQLD, 직장인 SQL)

1. 행의 구조를 지키는 집계의 신세계: 윈도우 함수의 본질

15화에서 우리는 데이터의 상세 행 구조를 파괴하지 않은 채 정밀한 순위를 매겨주고, 서브쿼리의 번거로움 없이 최신 1건의 이력 데이터만 신속하게 정제해 내는 테라데이터 전용 QUALIFY 절의 실무 리팩토링 치트키를 살펴보았습니다. 순위 함수를 통해 분석형 윈도우 함수의 기본 골격을 이해하고 나면, 분석가는 한 단계 더 확장하여 ‘상세 내역을 그대로 유지한 상태에서 행 간의 경계를 넘어 유연한 집계 연산을 수행해야 하는’ 고난도 요구사항과 마주하게 됩니다.

현업 실무나 대시보드 원천 데이터 가공 과정에서 자주 발생하는 요청은 대개 “일별 매출 상세 내역을 날짜 순서대로 보여주되, 우측 칼럼에 당월 누적 매출 합계(Cumulative Sum)를 나열해 달라”거나 “특정 상품의 일별 판매량 옆에 최근 3일간의 이동 평균(Moving Average)을 나열하여 트렌드를 분석할 수 있게 해달라”는 식의 연속형 통계치 산출입니다.

13화에서 배운 일반적인 GROUP BY 구문은 데이터를 지정한 기준에 따라 완전히 압축(Roll-up)하여 행의 수를 줄여버리기 때문에, 상세 내역 행과 요약 집계치를 한 화면에 나열하는 것이 불가능합니다. 이때 상세 행(Row) 데이터의 형태를 완벽히 유지하면서도, 우측 가상 칼럼에 실시간 집계 연산 결과를 유연하게 덧붙여 주는 강력한 도구가 바로 ‘집계 윈도우 함수(Aggregate Window Function)’입니다. 본 연작 시리즈는 대용량 처리에 활용되는 테라데이터 SQL 환경을 기준으로 OVER 절 기반의 집계 윈도우 함수 기초 문법과 실무 활용법을 설명하겠습니다.

2. OVER 절 기반 집계 윈도우 함수의 기본 문법 구조

일반적인 집계 함수인 SUM, AVG, COUNT 등은 뒤에 OVER 절이 붙는 순간, 데이터를 압축하는 속성을 버리고 각 행 옆에 연산 결과를 나열하는 윈도우 함수로 변모합니다. 누적 합계를 구하는 가장 표준적인 문법 구조는 다음과 같습니다.

-- 집계 윈도우 함수를 활용한 누적 합계 추출의 표준 문법 구조
SELECT 
    ITEM_CD
  , SALE_DT
  , SALE_AMT
  , SUM(SALE_AMT) OVER (
        PARTITION BY ITEM_CD     -- 집계 범위를 나눌 그룹 기준 (생략 가능)
        ORDER BY SALE_DT ASC     -- 누적 연산을 수행할 물리적 순서 기준
        ROWS UNBOUNDED PRECEDING -- 처음부터 현재 행까지의 연산 범위를 지정 (옵션)
    ) AS CUM_SALE_AMT
FROM 
    TABLE_NAME;

💡 윈도우 집계 구성 요소별 문법 규칙

  • PARTITION BY (집계 범위 제한): 전체 데이터를 특정 칼럼 기점으로 쪼개어 독립된 계산 영역(Partition)을 형성합니다. 위 예시에서는 상품코드(ITEM_CD)별로 방을 나누었기 때문에, 상품이 바뀌면 해당 상품 기준으로 누적 계산이 새롭게 시작됩니다.
  • ORDER BY (연산 순서 정의): 누적 집계를 수행할 때 데이터의 선후 관계를 규정하는 핵심 장치입니다. 일반적으로 과거부터 현재까지 누적합을 계산하기 위해 오름차순(ASC)을 사용합니다.
  • ROWS UNBOUNDED PRECEDING (윈도우 프레임): 현재 행을 기준으로 실제 연산에 포함시킬 물리적 행의 경계선(Window Frame)을 정밀하게 펜싱하는 문법입니다. UNBOUNDED PRECEDING은 ‘해당 파티션의 첫 번째 행부터 시작하여 현재 내가 서 있는 행까지’의 모든 데이터를 연산 대상으로 삼겠다는 의미를 내포합니다.

3. 현업 비즈니스 사례로 보는 실시간 누적 합계 가공 전략

집계 윈도우 함수가 실무 비즈니스 리포트나 시계열 트렌드 분석 과정에서 수많은 조인(Join)과 서브쿼리 노가다를 어떻게 우아하게 대체하는지, 실제 이커머스 매출 분석 부서에서 자주 겪는 가상의 시나리오를 통해 짚어보겠습니다.

📊 [실무 사례 예시: 마케팅 팀 강 대리의 일별 누적 실적 대시보드]

온라인 종합 쇼핑몰의 데이터 분석 담당자인 강 대리는 브랜드 영업 팀으로부터 주간 대시보드 연동을 위한 원천 데이터 추출 요청을 받았습니다.

  • 요청 내용: “7월 발생한 오프라인 매장의 일별 매출 내역을 날짜 순으로 나열해 주세요. 단, 매장 형태별로 매출 추이를 직관적으로 파악할 수 있도록, 상세 매출액 옆에 **’해당 매장 형태의 월별 실시간 누적 매출액’**을 계산하여 나열형 테이블로 구성해 주세요.”

만약 이 문제를 윈도우 함수 개념을 모르는 상태에서 해결하려고 했다면, 동일한 테이블을 자기 자신과 조인(Self Join)하거나 복잡한 상관 서브쿼리를 SELECT 절에 중첩해야 하므로 SQL이 매우 복잡해질 수 있습니다.

강 대리는 시스템 자원을 절약하고 코드를 간결하게 유지하기 위해 다음과 같이 SUM() OVER() 윈도우 함수 치트키를 활용한 마트 추출 쿼리를 빌드했습니다.

-- [올바른 예시] OVER 절을 활용하여 상세 내역과 누적 매출액을 단 한 번의 조회로 구현한 쿼리
SELECT 
    SHOP_TYPE_CD                               -- 매장 형태 코드 (대형마트, 백화점 등)
  , SALE_DT                                    -- 판매 일자
  , DAILY_SALE_AMT                             -- 당일 발생 매출액
  , SUM(DAILY_SALE_AMT) OVER (
        PARTITION BY SHOP_TYPE_CD              -- 매장 형태별로 계산 방을 격리
        ORDER BY SALE_DT ASC                   -- 날짜 순서대로 누적 연산 진행
        ROWS UNBOUNDED PRECEDING               -- 첫 날부터 당일까지의 데이터만 합산
    ) AS CUM_SALE_AMT                          -- 실시간 누적 매출액 칼럼 생성
FROM 
    DW_MART.DAILY_SHOP_SALES_SUMMARY
WHERE 
    BASE_YYMM = '202607'                       -- 7월 데이터로 모수 선제 압축
ORDER BY 
    SHOP_TYPE_CD ASC
  , SALE_DT ASC;

💡 리팩토링된 쿼리의 비즈니스 가치 분석

위 쿼리를 실행하면 데이터의 전체 행수가 압축되지 않고 일별 상세 내역(예: 7월 1일, 7월 2일…)이 그대로 유지되어 출력됩니다.

동시에 우측의 CUM_SALE_AMT 칼럼에는 당일 매출액이 누적되어 늘어나는 수치가 실시간으로 계산되어 출력됩니다. 이 덕분에 시각화 도구(Tableau 등)나 엑셀 차트와 연동했을 때, 매장 형태별로 매출이 우상향하는 기울기를 직관적인 그래프로 구현해 낼 수 있어 마케팅 팀이 실적 달성률을 정밀하게 모니터링하는 데 기여하는 훌륭한 밑거름이 됩니다.

4. 팩트 체크 및 데이터 분석가의 관점 점검 (윈도우 프레임의 생략 함정)

기술 콘텐츠의 정밀성과 신뢰성을 확보하기 위해, 실무에서 집계 윈도우 함수를 구사할 때 분석가들이 가장 많이 오해하거나 실수하는 사실 관계들을 명확히 점검해 보겠습니다.

  • OVER 절 내부에 ROWS UNBOUNDED PRECEDING 구문은 항상 생략해도 결과가 똑같은가?
    • 팩트 체크: 그렇지 않습니다. 데이터의 정렬 상태와 중복값 유무에 따라 결과가 완전히 달라질 수 있으므로 극도의 주의가 요구됩니다.
    • 만약 SUM(DAILY_SALE_AMT) OVER (PARTITION BY SHOP_TYPE_CD ORDER BY SALE_DT) 형태로 프레임 문법(ROWS...)을 완전히 생략하면, SQL 표준에서는 ORDER BY가 있는 경우 기본적으로 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW 프레임이 적용됩니다.
    • 만약 SALE_DT(판매 일자) 칼럼에 동일한 날짜를 가진 행(동일 일자 중복 데이터)이 여러 건 존재할 경우, ROWS 방식은 한 행 한 행 순차적으로 누적을 더해 가지만, RANGE 방식은 동일한 날짜를 가진 모든 행을 하나의 그룹(Peer Group)으로 간주하여 함께 계산합니다. 이로 인해 행 단위의 누적값 추이가 왜곡될 위험성이 존재하므로, 누적치를 구하는 실무 쿼리에서는 가능한 한 명시적으로 ROWS UNBOUNDED PRECEDING 구간을 기술해 주는 것이 안전한 대안으로 권장됩니다.
  • 윈도우 함수를 사용하면 GROUP BY 처럼 실행 속도가 무조건 느려지는가?
    • 팩트 체크: 일방적인 오해에 가깝습니다. 대용량 처리를 지원하는 최신 데이터베이스 및 테라데이터 환경에서는 상세 행 데이터를 복잡한 셀프 조인(Self-Join)이나 중첩 서브쿼리로 엮어 수차례 디스크를 긁어대던 과거 방식에 비해, 윈도우 함수를 단 1회 선언하여 메모리 내부 파티션 내에서 정렬 연산을 끝내는 방식이 훨씬 더 적은 자원을 소모하며 복잡한 Self Join이나 상관 서브쿼리보다 더 효율적으로 처리되는 경우가 많습니다. 따라서 “윈도우 함수는 무겁다”고 기피하기보다는, 적절한 날짜 필터(WHERE)와 조합하여 적극적으로 쿼리를 간결화하는 튜닝 접근이 바람직합니다.

5. 16화 요약 및 실무 윈도우 집계 자가 진단 체크리스트

쿼리를 최종 빌드하여 전사 데이터 마트 파이프라인에 이식하기 전, 연산의 논리적 결점이 없는지 스스로 진단할 수 있는 요약 가이드를 제공합니다.

체크포인트발생 가능한 실무 리스크현직 분석가의 권장 대안 및 조치
윈도우 내 ORDER BY 구문 누락 여부문법 에러가 발생하거나, 누적치가 아닌 전체 총합계가 복사되어 출력됨시간의 흐름이나 금액 크기를 규정하는 정렬 기준을 OVER 내부에 필수 기재
중복 데이터 환경에서의 프레임 생략동일 기준값을 가진 행들이 한꺼번에 합산되어 실시간 누적 추이 왜곡명시적으로 ROWS UNBOUNDED PRECEDING을 기재하여 행 단위 순차 연산 보장
WHERE 절에 윈도우 함수 직접 사용윈도우 함수는 WHERE 절에서 직접 사용할 수 없으므로 오류가 발생함15화에서 다룬 QUALIFY 절을 활용하거나 서브쿼리 레이아웃으로 변환 유도

6. 결론 및 다음 화 예고

이번 16화에서는 데이터의 상세 구조를 파괴하지 않으면서도 행 간의 경계를 넘어 실시간 시계열 누적치나 요약 통계를 유연하게 산출하는 집계 윈도우 함수의 기초 문법과 비즈니스 대시보드 리팩토링 사례를 다각도로 점검해 보았습니다. 상세 데이터와 통계 요약치를 하나의 파이프라인 안에서 유기적으로 결합해 내는 역량은 고도화된 데이터 모델링을 구현하기 위한 강력한 무기가 됩니다.

행 단위를 유지하며 누적합을 구하는 방식을 마스터한 분석가가 다음 단계로 확장하게 되는 영역은, 현재 행을 기준으로 과거 행이나 미래 행을 자유자재로 소환하여 비교 분석하는 일입니다.

이어지는 17화에서는 윈도우 함수 계열 중 실무 시계열 분석의 끝판왕이자 최고봉으로 평가받는 LAGLEAD 함수의 세계를 집중 분석합니다. 서브쿼리 없이 단 한 줄의 명령어로 전월 매출 데이터(LAG)나 다음 달 예약 데이터(LEAD)를 현재 행 옆으로 즉시 소환하는 문법 구조를 살펴보고, 이를 활용해 전월 대비 증감률(MoM) 및 트렌드 변동 지표를 정밀하게 가공하는 현직 분석가들의 핵심 실무 치트키를 상세히 파악해 보겠습니다.

댓글 남기기