
1. 다차원 요약 보고서의 당면 과제: 계층별 소계와 총계
13화에서 우리는 낱개의 로우 데이터 파편들을 특정 기준 칼럼에 따라 그룹별로 묶어 비즈니스 지표를 산출해 내는 통계 분석의 핵심인 GROUP BY 문법 구조와 필수 집계 함수 4종(COUNT, SUM, MIN, MAX)의 메커니즘을 살펴보았습니다. 단일 기준에 따른 요약 보고서를 완벽하게 마스터하고 나면, 분석가는 한 단계 더 나아가 보고서의 입체적인 서식을 완성해야 하는 정교한 과제와 마주하게 됩니다.
현업에서 경영진이나 기획 부서에 제공하는 보고서의 레이아웃은 대개 “년도별, 월별 매출액을 나열하되, 각 월별 소계와 년도별 소계, 그리고 마지막 영역에는 전체 총합계(Grand Total)를 한눈에 볼 수 있도록 구성해 달라”는 식의 계층적 구조를 취하곤 합니다. 이러한 보고서를 일반적인 GROUP BY 절만으로 구현하려고 하면, 월별 집계 쿼리와 년도별 집계 쿼리, 총합계 쿼리를 각각 따로 작성한 뒤 여러 단계의 집계 쿼리를 UNION ALL로 반복 결합해야 하는 복잡한 코드가 작성되기 쉽습니다.
이처럼 여러 층위의 중간 소계(Subtotal)와 최종 총합계를 단 하나의 명령어 조합으로 깨끗하게 자동 도출해 주는 확장 문법이 바로 GROUP BY ROLLUP 구문입니다. 본 연작 시리즈는 기업형 대용량 데이터 처리에 널리 쓰이는 테라데이터 SQL 환경을 기준으로 ROLLUP 구문의 문법 규칙과 실무 요약 전략을 설명하겠습니다.
2. GROUP BY ROLLUP의 기본 문법 구조와 작동 메커니즘
ROLLUP 구문은 기본 표준 SQL 문법 규칙상 GROUP BY 키워드 바로 뒤에 위치하며, 소계를 구하고자 하는 칼럼들을 괄호 안에 계층적인 순서대로 나열하는 방식을 취합니다. 이때 나열된 칼럼의 순서에 따라 대그룹, 중그룹, 소그룹의 방향성을 인지하여 오른쪽 칼럼부터 집계 기준에서 제외하면서 상위 레벨의 소계와 총합계를 단계적으로 생성하는 메커니즘을 가집니다.
-- GROUP BY ROLLUP의 가장 표준적인 문법 구조
SELECT
LARGE_CATEGORY_CD -- 대그룹 (예: 본부)
, MEDIUM_CATEGORY_CD -- 중그룹 (예: 부서)
, SUM(SALE_AMT) AS TOTAL_AMT
FROM
TABLE_NAME
GROUP BY ROLLUP (
LARGE_CATEGORY_CD
, MEDIUM_CATEGORY_CD -- 오른쪽 칼럼부터 순차적으로 그룹 해제하며 소계 산출 유도
);
💡 ROLLUP 구문이 생성해내는 계층 구조 분석
GROUP BY ROLLUP (A, B) 구조로 쿼리를 실행하면, 시스템은 사용자가 여러 개의 쿼리를 따로 짜서 합친 것과 동일한 다음 3가지 층위의 데이터셋을 단 한 번에 연산하여 위아래로 정돈된 단일 테이블로 반환합니다.
- [A, B] 그룹 조합: 가장 상세한 단위인 대그룹+중그룹별 기본 집계 결과
- [A] 그룹 조합: 오른쪽의 B 칼럼을 제외한 ‘대그룹별 중간 소계(Subtotal)’ 결과
- [전체 공백] 조합: 모든 그룹 기준을 제외한 ‘전체 최종 총합계(Grand Total)’ 결과
이때 중간 소계나 총합계 영역처럼 특정 그룹 기준이 제외된 행의 칼럼 자리에는 데이터베이스 문법 규칙상 자동으로 NULL 값이 채워져서 출력되는 특성을 보입니다.
3. 현업 비즈니스 사례로 보는 ROLLUP 리팩토링 전략
ROLLUP 구문이 실무 매출 실적 장표 작성 과정에서 수백 줄의 지저분한 스파게티 코드를 어떻게 우아하게 리팩토링하고 업무 생산성을 끌어올리는지, 실제 유통 대기업이나 이커머스 분석 부서에서 자주 발생하는 가상의 시나리오를 통해 짚어보겠습니다.
📊 [실무 사례 예시: 영업 기획 팀 박 대리의 매장별 계층 실적 보고서]
대형 백화점의 영업 분석 담당자인 박 대리는 주간 전사 실적 회의를 앞두고 마케팅 부서로부터 다음과 같은 계층형 데이터 요약 장표 추출 요청을 받았습니다.
- 요청 내용: “당사 오프라인 매장의 ‘지역본부별’ 및 그 하위 ‘세부 점포별’ 7월 누적 매출액을 구해주세요. 단, 각 지역본부가 끝나는 행에는 본부별 매출 소계가 들어가야 하고, 리포트의 가장 마지막 행에는 전사 총 매출액 합계가 누락 없이 단 하나의 결과 창에 포개어져 나와야 합니다.”
만약 이 문제를 ROLLUP 개념을 모르는 입문자나 초보 직장인이 해결하려고 했다면, 다음과 같이 12화에서 배운 UNION ALL 연산자를 연발하는 거대하고 비효율적인 코드를 작성했을 가능성이 큽니다.
-- [비효율적 예시] 동일한 테이블을 세 번이나 중복 조회하여 UNION ALL로 이어 붙인 노가다 쿼리
-- 1층위: 본부별, 점포별 상세 매출
SELECT REGION_HQ, SHOP_NM, SUM(SALE_AMT) FROM DW_MART.DAILY_SALES GROUP BY REGION_HQ, SHOP_NM
UNION ALL
-- 2층위: 본부별 중간 소계 (SHOP_NM 자리를 '소계' 문자열로 고정)
SELECT REGION_HQ, '본부소계' AS SHOP_NM, SUM(SALE_AMT) FROM DW_MART.DAILY_SALES GROUP BY REGION_HQ
UNION ALL
-- 3층위: 전사 최종 총합계 (HQ와 SHOP 자리를 전부 고정 문자열로 채움)
SELECT '전사총계' AS REGION_HQ, '전사총계' AS SHOP_NM, SUM(SALE_AMT) FROM DW_MART.DAILY_SALES;
위 쿼리는 작성하는 데 시간이 오래 걸릴 뿐 아니라, 동일한 대용량 원천 테이블을 여러 번 조회하고 집계해야 하는 구조이므로 불필요한 데이터 읽기와 집계 비용이 증가할 가능성이 있습니다. 박 대리는 이러한 비효율을 걷어내고 코드를 구조화하기 위해 다음과 같이 GROUP BY ROLLUP 치트키를 활용한 리팩토링 쿼리를 설계하여 단 몇 줄만으로 상황을 해결했습니다.
-- [올바른 예시] GROUP BY ROLLUP을 활용해 단 하나의 집계 SQL로 소계와 총계를 구현한 ROLLUP 적용 쿼리
SELECT
CASE
WHEN GROUPING(REGION_HQ)=1 THEN 'TOTAL'
ELSE REGION_HQ
END AS REGION_HQ,
CASE
WHEN GROUPING(SHOP_NM)=1 THEN 'SUBTOTAL'
ELSE SHOP_NM
END AS SHOP_NM,
SUM(SALE_AMT) AS TOTAL_SALES_AMT
FROM DW_MART.DAILY_SALES
WHERE BASE_YYMM='202607'
GROUP BY ROLLUP(REGION_HQ, SHOP_NM);
💡 리팩토링된 쿼리의 비즈니스적 가치 및 문법 응용 포인트
- GROUPING 함수와의 완벽한 시너지: 앞서 언급했듯이
ROLLUP연산 결과 중간 소계나 총합계가 계산된 행의 기준 칼럼 자리는 시스템이NULL을 뿜어냅니다. 이를 화면에 방치하면 빈칸으로 출현하여 가독성이 낮아집니다. 박 대리는 이 지점에 GROUPING 함수를 결합하여, ROLLUP 연산으로 생성된 NULL과 원본 데이터의 NULL을 구분한 뒤 소계 및 총합계 행의 명칭을 명확하게 가공했습니다. - 시스템 리소스의 획기적 절약:
ROLLUP구문은 동일한 원천 데이터를 반복 조회하는 UNION ALL 방식보다 하나의 집계 처리 흐름 안에서 여러 단계의 집계를 수행할 수 있어, 불필요한 반복 스캔과 중복 SQL 작성을 줄이는 데 효과적입니다.
4. 팩트 체크 및 데이터 분석가의 관점 점검
기술 콘텐츠의 객관성과 신뢰성을 유지하기 위해, 실무에서 ROLLUP 확장 구문을 구사할 때 분석가들이 가장 많이 오해하거나 혼동하는 사실 관계들을 명확히 점검해 보겠습니다.
- ROLLUP 괄호 안에 나열하는 칼럼의 순서를 바꾸어도 결과는 동일한가?
- 팩트 체크: 절대 그렇지 않습니다.
GROUP BY ROLLUP (A, B)와GROUP BY ROLLUP (B, A)는 완전히 다른 계층 구조의 결과물을 생성해 냅니다.ROLLUP은 나열된 순서에 뚜렷한 상하 계층(Hierarchy) 관계가 존재한다고 가정하고 작동합니다. 즉, 앞에 적힌 칼럼이 ‘대그룹(상위 층위)’이 되고 뒤에 적힌 칼럼이 ‘소그룹(하위 층위)’이 됩니다. 만약 순서를 바꾸어ROLLUP (SHOP_NM, REGION_HQ)로 기재하면 ‘점포별 중간 소계’라는 비즈니스 맥락에 맞지 않는 엉뚱한 기준의 소계 행이 산출되므로, 반드시 크고 넓은 그룹 단위를 괄호 안의 왼쪽에 배치해야 문법적 오류를 예방할 수 있습니다.
- 팩트 체크: 절대 그렇지 않습니다.
- 소계나 총합계 행에서 발생하는 NULL과 원천 데이터 자체의 NULL은 어떻게 구별하는가?
- 팩트 체크: 현업에서 발생하는 매우 날카로운 질문 중 하나입니다. 만약 원천 테이블 자체에 점포명이 입력되지 않은 결측치(
NULL) 고객 행이 원래 존재했다면,ROLLUP이 소계를 내기 위해 임의로 만들어낸NULL과 화면상에서 모양이 똑같아 구별하기 어려워지는 모호성이 발생할 수 있습니다. 표준 SQL에서는 이를 명확히 분별하기 위해GROUPING(칼럼명)이라는 전용 내장 함수를 제공합니다. 이 함수는 해당 행의NULL이ROLLUP연산에 의해 생성된 소계/총계 행이면 숫자1을 반환하고, 원본 데이터 값이 NULL인 경우에는0을 반환합니다. 따라서 향후 고도화된 스크립트를 빌드할 때는CASE WHEN GROUPING(SHOP_NM) = 1 THEN '소계'형태로 매칭하는 것이 완벽한 팩트 가공의 표준 대안으로 꼽힙니다.
- 팩트 체크: 현업에서 발생하는 매우 날카로운 질문 중 하나입니다. 만약 원천 테이블 자체에 점포명이 입력되지 않은 결측치(
5. 14화 요약 및 실무 계층 집계 자가 진단 체크리스트
쿼리를 최종 빌드하여 전사 대시보드 스크립트에 상정하기 전, 데이터 집계의 논리적 결점이 없는지 스스로 진단할 수 있는 요약 가이드를 제공합니다.
| 체크포인트 | 발생 가능한 실무 리스크 | 현직 분석가의 권장 대안 및 조치 |
| ROLLUP 내 칼럼 배치 순서의 적절성 | 상하 계층 구조가 뒤바뀌어 비즈니스 맥락에 맞지 않는 엉뚱한 중간 소계 산출 | 괄호 내부에 [대분류 -> 중분류 -> 소분류] 순서로 칼럼이 나열되었는지 재검토 |
| 소계 행의 공백(NULL) 방치 여부 | 최종 출력 화면이나 엑셀 다운로드 시 빈칸으로 남아 시각적 미완성성 노출 | GROUPING 함수와 CASE WHEN을 활용하여 '소계', '총합계' 등 텍스트 치환 처리 |
| 과도한 다수 칼럼의 ROLLUP 적용 | 조합해야 할 계층 가짓수가 기하급수적으로 늘어나 자원 과부하 유발 | 꼭 필요한 핵심 계층 칼럼 2~3개 내외로 제한하여 유도하거나 부분 롤업 활용 |
6. 결론 및 다음 화 예고
이번 14화에서는 일반적인 그룹화를 확장하여 단 한 번의 조회만으로 대그룹, 중그룹의 중간 소계와 전사 최종 총합계를 입체적으로 나열하는 GROUP BY ROLLUP 확장 구문의 특성을 살펴보고, GROUPING 함수와의 융합을 통한 대시보드 데이터 규격화 전략을 다각도로 점검해 보았습니다. 수많은 UNION ALL 노가다 코드를 단 몇 줄의 집계 확장 구문으로 리팩토링해 내는 역량은 분석가의 생산성을 배로 높여주는 강력한 무기가 됩니다.
계층별 요약 통계를 산출하는 기법을 마스터한 분석가가 다음 단계로 마주하게 되는 현업의 고난도 요구사항은, 데이터의 행 수나 구조를 파괴하지 않은 채 ‘개별 행 옆에 순위나 누적치’를 정밀하게 나열하는 일입니다.
이어지는 15화에서는 추출된 데이터 결과 내에서 특정 그룹별 순위를 1등부터 순서대로 안전하게 매겨주는 일등 공신인 ROW_NUMBER 순위 함수의 세계를 집중 분석합니다. 특히 대용량 거래 데이터 환경에서 중복 적재된 이력 데이터 중 가장 최신의 계약 데이터 딱 1건만 남기고 나머지를 깨끗하게 솎아내는 현직자들의 핵심 중복 제거 치트키이자 테라데이터에서 대표적으로 활용되는 QUALIFY 절의 문법 구조를 비즈니스 사례와 함께 상세히 파악해 보겠습니다.