SUM으로 열을 더하다 보면 금방 벽을 만납니다. 매출은 수량에 단가를 곱해야 나오는데, 우리 표에는 “매출” 열이 없는 경우가 많거든요. 열을 하나 더 만들어 둘 수도 있지만, 측정값 안에서 바로 계산하고 싶을 때 쓰는 함수가 SUMX입니다. 이름 끝의 X는 “행마다 식을 계산한다”는 뜻으로 이해하면 편합니다.
SUMX가 하는 일
SUMX( <테이블>, <식> )
첫 번째 인수로 받은 테이블을 한 줄씩 돌면서, 그 줄 기준으로 두 번째 인수의 식을 계산하고, 결과를 모두 더합니다. 이렇게 행을 하나씩 도는 함수를 반복 함수(iterator)라고 부릅니다. 반환값은 소수 형태의 숫자입니다.
Microsoft 문서에 따르면 첫 번째 인수는 테이블 자체이거나 테이블을 돌려주는 식이어도 됩니다. 그리고 계산 결과 중 숫자만 더해지고, 빈 값과 논리값(TRUE/FALSE), 텍스트는 무시됩니다.
예제 데이터
앞선 SUM 함수 글과 같은 가상 데이터를 씁니다. 단가는 만원 단위이고, 결과는 Power BI에서 돌린 화면이 아니라 직접 계산해서 적은 값입니다.
| 주문 | 상품 | 수량 | 단가 |
|---|---|---|---|
| 1 | 노트북 | 1 | 120 |
| 2 | 마우스 | 3 | 4 |
| 3 | 모니터 | 2 | 20 |
| 4 | 마우스 | 5 | 4 |
| 5 | 노트북 | 2 | 100 |
기본: 수량 곱하기 단가
총매출 =
SUMX(
Sales,
Sales[수량] * Sales[단가]
)
행마다 120, 12, 40, 20, 200이 계산되고 합은 392입니다. SUM으로는 이 계산을 한 번에 할 수 없습니다. SUM은 열 하나만 받기 때문입니다.
식 안에서 조건을 쓰기
노트북만 10% 할인한 매출을 보고 싶다고 해 보겠습니다. 행마다 조건에 따라 곱하는 값이 달라지니 이것도 SUMX의 영역입니다.
할인후매출 =
SUMX(
Sales,
Sales[수량] * Sales[단가]
* IF( Sales[상품] = "노트북", 0.9, 1 )
)
노트북 두 줄(120, 200)은 각각 108, 180이 되고 나머지 세 줄(12, 40, 20)은 그대로라서 합계가 360입니다. 원래 매출 392에서 노트북 매출 320의 10%인 32가 빠진 값과 같습니다.
테이블 자체를 걸러서 넘기기
Microsoft 문서의 예제처럼 첫 번째 인수에 FILTER를 넣어서 일부 행만 더할 수도 있습니다.
노트북매출 =
SUMX(
FILTER( Sales, Sales[상품] = "노트북" ),
Sales[수량] * Sales[단가]
)
결과는 120 + 200 = 320입니다. 같은 값을 CALCULATE로도 만들 수 있습니다.
노트북매출 =
CALCULATE( [총매출], Sales[상품] = "노트북" )
두 방식 모두 320이 나옵니다. 어느 쪽이든 되지만, SQLBI는 테이블 전체를 FILTER로 거는 것보다 열 하나에 조건을 거는 쪽이 더 가볍고 안전하다고 설명합니다. 필터링이 목적이라면 CALCULATE 쪽을 먼저 고려해 볼 만합니다. 자세한 내용은 CALCULATE 함수 글에 적어 두었습니다.
측정값을 행마다 평가하는 패턴
SUMX는 테이블뿐 아니라 “상품 목록” 같은 값 목록 위에서도 많이 돌립니다. 예를 들어 상품별 매출 중 100을 넘는 상품만 합치고 싶다면 이렇게 씁니다.
큰상품매출 =
SUMX(
VALUES( Sales[상품] ),
IF( [총매출] > 100, [총매출] )
)
VALUES가 현재 필터 상태의 상품 목록(노트북, 마우스, 모니터)을 돌려주고, SUMX가 그 상품을 하나씩 돌면서 [총매출]을 계산합니다. 상품별 매출은 노트북 320, 마우스 32, 모니터 40이니 100을 넘는 것은 노트북뿐이라 결과는 320입니다.
여기서 눈여겨볼 점이 있습니다. 반복 안에서 측정값을 쓰면 “지금 도는 행의 상품”이 자동으로 필터로 바뀌어서 그 상품의 매출이 계산됩니다. 이것이 행 컨텍스트가 필터 컨텍스트로 바뀌는 컨텍스트 전환입니다. 측정값 참조는 내부적으로 CALCULATE를 감싸는 것과 같다고 SQLBI와 Microsoft 문서가 설명합니다. DAX Guide의 SUMX 페이지에도, 행 컨텍스트 안에서 호출되면 컨텍스트 전환이 일어난다는 설명이 있습니다.
변수를 돌릴 때도 SUMX
DAX Guide는 SUMX가 필요한 상황으로 “변수에 담긴 테이블을 반복할 때”를 따로 꼽습니다. SUM은 모델에 있는 열만 받기 때문에, VAR로 만든 임시 테이블의 열은 더할 수 없습니다. 그럴 때 SUMX를 씁니다.
SUM과의 관계
DAX Guide에는 “SUM은 열 하나에 쓴 SUMX의 줄임 표현”이라고 적혀 있고, 둘 사이에 성능 차이는 없다고 합니다. 그러니 이렇게 정리하면 됩니다.
- 열 하나를 그대로 더한다 → SUM
- 행마다 식을 계산해서 더한다 → SUMX
Microsoft 문서도 마지막에 “열을 걸러낼 필요가 없다면 SUM을 쓰라”고 덧붙입니다.
쓸 때 주의할 점
- SUMX는 행을 하나씩 도는 함수라서, 반복하는 식이 무거우면 그만큼 느려질 수 있습니다. 반복 안에 또 반복을 넣는 중첩은 특히 조심해야 합니다. 이런 비용을 줄이는 최적화 기법이 있다고 DAX Guide가 관련 글을 안내합니다.
- 합산되는 것은 숫자뿐입니다. 식의 결과가 빈 값, 논리값, 텍스트이면 무시됩니다.
- DirectQuery 모드에서는 계산 열이나 행 수준 보안 규칙 안에서 쓸 수 없다고 Microsoft 문서에 적혀 있습니다. 측정값에서는 쓸 수 있습니다.
- 첫 번째 인수는 “더할 행이 담긴 테이블”입니다. 열이 아니라 테이블을 넣는다는 점을 헷갈리기 쉽습니다.
자주 하는 실수
- SUM으로 곱셈 합계를 구하려는 경우: SUM(수량) × SUM(단가)는 3,224가 나옵니다. 행마다 곱하는 SUMX는 392입니다.
- 첫 인수에 열을 넣는 경우: SUMX( Sales[수량], … )처럼 쓰면 안 됩니다. 테이블이 와야 합니다.
- 반복 안에서 측정값이 예상과 다른 경우: 컨텍스트 전환이 일어나는 것이 정상 동작인지 먼저 확인해 보세요.
비슷한 함수
- SUM: 열 하나의 합계
- AVERAGEX, MINX, MAXX, COUNTX: 같은 방식으로 행마다 계산한 뒤 평균, 최소, 최대, 개수를 구하는 반복 함수
- CALCULATE: 반복이 아니라 필터를 바꿔서 계산하는 함수
정리
SUMX는 “행마다 계산하고 더한다”는 한 문장으로 요약됩니다. 곱셈이나 조건이 섞인 합계는 SUMX, 단순 합계는 SUM, 조건만 바꾸고 싶다면 CALCULATE로 구분해 두면 이후 함수들도 훨씬 수월합니다. 예제는 가상 데이터이니 본인 모델의 열 이름으로 바꿔 직접 확인해 보시고, 동작은 버전에 따라 다를 수 있어 공식 문서도 함께 보시길 권합니다.
참고한 자료
- Microsoft Learn, SUMX function (DAX): https://learn.microsoft.com/en-us/dax/sumx-function-dax
- DAX Guide, SUMX: https://dax.guide/sumx/
- SQLBI, Context transition in DAX explained visually: https://www.sqlbi.com/articles/context-transition-in-dax-explained-visually/
- SQLBI, Introducing CALCULATE in DAX: https://www.sqlbi.com/articles/introducing-calculate-in-dax/
“DAX SUMX 함수 정리: 행마다 계산해서 더할 때 쓰는 반복 함수”에 대한 1개의 생각