가장 최근 주문일, 가장 비싼 단가, 두 값 중 큰 쪽. 이런 “가장 큰 값”이 필요할 때 쓰는 함수가 MAX입니다. 앞서 정리한 MIN 함수 글의 거울 같은 함수라서 사용법은 거의 같습니다. 그래서 오히려 같은 지점에서 같은 실수를 하기 쉽습니다. 열 하나를 받는 형태와 값 두 개를 받는 형태가 따로 있고, 두 번째 형태에서 빈 값을 다루는 방식이 문서마다 다르게 적혀 있다는 점이 특히 그렇습니다. 이 글에서는 두 형태의 차이, 실무에서 자주 쓰는 세 가지 상황, 그리고 빈 값에서 조심할 점을 정리합니다.
문법: 두 가지 형태
MAX( <열> )
MAX( <식1>, <식2> )
Microsoft 문서의 설명대로 MAX는 “열에서 가장 큰 값, 또는 두 식 사이에서 더 큰 값”을 돌려줍니다. 열 형태에 날짜를 쓰면 가장 최근 날짜가 반환되고, DAX Guide는 문자열은 알파벳(사전) 순서로 비교하며 논리값은 무시한다고 설명합니다. 값이 있는 행이 하나도 없으면 빈 값을 돌려줍니다.
Power BI Desktop에서 측정값으로 만들기
메뉴 이름은 Power BI 버전과 언어 설정에 따라 조금 다를 수 있다는 점을 먼저 말씀드립니다. 일반적인 순서는 이렇습니다.
- 보고서 보기에서 오른쪽 필드 창의 테이블(예: Sales)을 선택합니다.
- 상단 리본에서 “새 측정값”(영문판은 New measure)을 누릅니다.
- 수식 입력줄에
최고단가 = MAX( Sales[단가] )처럼 이름과 식을 적고 Enter를 누릅니다. - 만든 측정값을 표 시각화에 올리고 상품 같은 열과 함께 놓아 줄마다 값이 어떻게 달라지는지 확인합니다.
예제 데이터
앞선 SUM, SUMX, AVERAGE 글과 이어지는 가상 데이터입니다. 결과는 Power BI에서 돌린 화면이 아니라 직접 구한 값이니, 같은 식을 본인 데이터에 적용해서 확인해 보세요.
| 주문 | 주문일 | 상품 | 수량 | 단가 |
|---|---|---|---|---|
| 1 | 3/2 | 노트북 | 1 | 120 |
| 2 | 3/3 | 마우스 | 3 | 4 |
| 3 | 3/5 | 모니터 | 2 | 20 |
| 4 | 3/7 | 마우스 | 5 | 4 |
| 5 | 3/9 | 노트북 | 2 | 100 |
실무 시나리오 1: 가장 최근 날짜와 가장 높은 값
마지막주문일 = MAX( Sales[주문일] )
최고단가 = MAX( Sales[단가] )
마지막 주문일은 3/9(5번 주문)이고, 최고 단가는 노트북의 120입니다. 상품별 표에 올리면 상품마다 따로 계산됩니다.
| 상품 | 마지막주문일 | 최고단가 |
|---|---|---|
| 노트북 | 3/9 | 120 |
| 마우스 | 3/7 | 4 |
| 모니터 | 3/5 | 20 |
| 합계 | 3/9 | 120 |
노트북은 단가 120과 100 중 큰 120입니다. 합계 줄은 줄들의 값을 다시 모은 것이 아니라 필터 없이 전체에서 새로 구한 값이고, 최댓값은 그 결과가 우연히 줄들의 최댓값과 같아 보일 뿐입니다. 이 “마지막 주문일”은 “마지막 주문 이후 며칠이 지났는가” 같은 경과일 계산의 출발점으로 자주 쓰입니다.
실무 시나리오 2: 두 값 중 큰 값으로 하한 두기
MAX의 두 번째 형태는 “더 큰 쪽을 고른다”는 뜻이라서, 값에 하한을 둘 때 씁니다. 예를 들어 수당을 계산할 때 실적에 따른 금액이 있더라도 최소 보장액 50보다 낮아지지는 않게 하는 규칙입니다.
지급수당 =
MAX( [실적수당], [최소보장액] )
| 팀 | 실적수당 | 최소보장액 | 지급수당 |
|---|---|---|---|
| A | 30 | 50 | 50 |
| B | 80 | 50 | 80 |
A팀은 실적수당 30이 보장액보다 작으니 50이 지급되고, B팀은 80이 더 크니 80이 지급됩니다. MIN으로 상한을 두는 것과 정반대의 쓰임입니다. 다만 이 형태는 두 값 중 하나가 빈 값일 때 결과가 문서마다 다르게 적혀 있으니, 아래 “빈 값” 항목을 꼭 확인하세요.
실무 시나리오 3: 계산한 값들의 최댓값 (MAXX)
MAX는 모델에 있는 열을 받습니다. 수량 × 단가처럼 행마다 계산한 값의 최댓값은 MAXX를 씁니다.
최대주문금액 =
MAXX(
Sales,
Sales[수량] * Sales[단가]
)
행마다 120, 12, 40, 20, 200이 계산되므로 최댓값은 200(5번 주문)입니다. DAX Guide는 열 하나에 쓴 MAX가 내부적으로 MAXX를 실행하는 것과 같고 성능 차이가 없다고 설명합니다. MAX는 모델의 열에만 쓸 수 있으니, 계산한 값이나 변수의 내용을 돌아야 할 때는 MAXX가 필요합니다. MAXX는 선택 인수가 하나 더 있는데, 이 글에서는 다루지 않습니다.
MAXX는 측정값을 그룹별로 계산한 뒤 그중 최댓값을 구할 때도 씁니다. “상품별 총매출 중 가장 큰 매출”은 이렇게 구합니다.
총매출 = SUMX( Sales, Sales[수량] * Sales[단가] )
최대상품매출 =
MAXX(
VALUES( Sales[상품] ),
[총매출]
)
최대상품비중 =
DIVIDE( [최대상품매출], [총매출] )
상품별 총매출은 노트북 320, 마우스 32, 모니터 40이라서 최대 상품 매출은 320이고, 전체 총매출 392 중 비중은 320 ÷ 392 = 약 81.6%입니다. 한두 상품에 매출이 쏠려 있는지 확인하는 지표로 쓸 수 있습니다. 반복 안에서 측정값을 부르면 “지금 도는 상품”이 필터로 바뀌는 컨텍스트 전환이 일어납니다(CALCULATE 함수 글 참고).
빈 값: 설명이 서로 다른 부분
MIN과 마찬가지로 빈 값 처리는 MAX에서 가장 조심해야 할 부분입니다. 문서를 비교해 보니 서로 다르게 적혀 있는 대목이 있어서, 확인된 내용과 갈리는 내용을 나눠 정리합니다.
- 열 형태: 빈 값은 건너뛰고, 값이 있는 행이 하나도 없으면 빈 값을 돌려준다고 DAX Guide가 설명합니다. 논리값(TRUE/FALSE)은 지원하지 않고, 필요하면 MAXA를 쓴다고 Microsoft 문서가 안내합니다.
- 두 값 형태: 여기서 설명이 갈립니다. DAX Guide는 두 값 형태에서 MAX가 빈 값을 “의미 있는 값”으로 취급하며,
MAX( -2, BLANK() )의 결과가 빈 값이라고 설명하고, MAXX로 같은 비교를 하면 빈 값이 무시되어 -2가 나온다고 대비합니다. 반면 Microsoft 문서는 비교할 때 빈 값이 0으로 취급된다고 적고, 예로MAX( 1, BLANK() )이 1,MAX( -1, BLANK() )이 0을 돌려준다고 설명합니다. 둘 다 “빈 값이 열 형태처럼 그냥 무시되지는 않는다”는 점은 같지만, 음수와 비교할 때 결과가 다르게 적혀 있습니다.
어느 쪽 설명이 지금 쓰는 버전에 맞는지는 이 글에서 단정할 수 없습니다. 제가 Power BI에서 직접 돌려 확인한 것이 아니기 때문입니다. 그래서 빈 값 가능성이 있는 두 값을 MAX에 넣기 전에 미리 처리하는 것이 안전합니다.
지급수당_안전 =
VAR 실적값 = [실적수당]
VAR 보장값 = [최소보장액]
RETURN
IF(
ISBLANK( 실적값 ),
보장값,
MAX( 실적값, 보장값 )
)
이렇게 “실적수당이 비어 있으면 보장액을 지급한다”처럼 빈 값일 때의 결과를 식에서 직접 정해 두면 어느 쪽 설명이 맞더라도 결과가 흔들리지 않습니다. 이 규칙이 업무에 맞는지는 별도로 정해야 합니다. 빈 값을 0으로 바꾸는 방법도 있지만, SQLBI의 글(빈 값 대신 0을 반환하는 방법)이 지적하듯 데이터가 없는 구간까지 0이 표시되는 부작용이 있습니다.
텍스트 열에도 쓸 수 있을까
MIN 글에서 소개한 것처럼, SQLBI의 2015년 글은 MIN과 MAX를 텍스트 열에는 쓸 수 없다고 하면서 FIRSTNONBLANK, LASTNONBLANK를 대안으로 제시했습니다. 현재 DAX Guide는 문자열을 알파벳 순서로 비교한다고 설명하니, 버전에 따라 동작이 달라졌을 수 있습니다. 텍스트 열에 쓸 계획이라면 사용하는 환경에서 직접 확인해 보세요.
쓰지 말아야 할 때
- TRUE/FALSE 열: MAX는 지원하지 않습니다. MAXA를 쓰세요.
- 계산한 값이나 변수의 최댓값: 열이 아니라 식이므로 MAXX를 써야 합니다.
- 빈 값이 섞일 수 있는 두 값 비교: 위처럼 미리 처리하세요.
- “가장 큰 값”이 아니라 “그 값을 가진 행의 다른 열”이 필요할 때: 예를 들어 최고 단가 상품의 이름은 MAX 하나로 구할 수 없습니다. 다른 함수와 함께 써야 합니다.
알아둘 점
- DAX Guide는 MAX가 DirectQuery의 측정값과 계산 열에서 지원된다고 안내합니다.
- 한 열의 데이터 형식은 하나입니다. 숫자 열이면 숫자끼리, 날짜 열이면 날짜끼리 비교합니다.
- 지역 설정에 따라 인수 구분자가 쉼표 대신 세미콜론일 수 있습니다. 식을 붙여 넣었는데 오류가 난다면 먼저 확인해 보세요.
자주 하는 실수
- 합계 줄이 줄별 값의 최댓값과 같은 이유를 모름: 필터 없이 새로 계산한 값이고, 결과가 우연히 일치할 수 있습니다.
- 두 값 형태에서 빈 값 때문에 의도와 다른 결과: 문서마다 다르게 설명하는 부분이라 미리 처리하는 것이 안전합니다.
- 계산식을 MAX에 바로 넣음: MAX( Sales[수량] * Sales[단가] )처럼 쓰면 안 되고, MAXX가 필요합니다.
- 논리값 열에 MAX: 지원하지 않습니다.
비슷한 함수
- MIN: 가장 작은 값. 사용법이 같습니다.
- MAXX, MINX: 행마다 계산한 값의 최댓값, 최솟값
- MAXA: 논리값까지 처리하는 형태
- FIRSTDATE, LASTDATE: 날짜 열에서 첫 날짜와 마지막 날짜. 시간 비교 계산에서 자주 쓰입니다.
정리
MAX는 열의 최댓값(또는 가장 최근 날짜)과 두 값 중 큰 값, 두 가지 용도로 나눠 기억하면 됩니다. 계산한 값의 최댓값은 MAXX, 논리값은 MAXA, 그리고 빈 값이 섞일 수 있는 두 값 비교는 미리 처리해 두는 것이 안전합니다. 예제는 가상 데이터이니 본인 모델의 열 이름으로 바꿔 직접 확인해 보시고, 특히 빈 값이 있는 데이터에서는 결과를 꼭 눈으로 확인해 보세요. 동작은 버전에 따라 다를 수 있어 공식 문서도 함께 보시길 권합니다.
참고한 자료
- Microsoft Learn, MAX function (DAX): https://learn.microsoft.com/en-us/dax/max-function-dax
- Microsoft Learn, MAXX function (DAX): https://learn.microsoft.com/en-us/dax/maxx-function-dax
- DAX Guide, MAX: https://dax.guide/max/
- DAX Guide, MAXX: https://dax.guide/maxx/
- SQLBI, How to return 0 instead of BLANK in DAX: https://www.sqlbi.com/articles/how-to-return-0-instead-of-blank-in-dax/
- SQLBI, Use FIRSTNONBLANK and LASTNONBLANK instead of MIN and MAX (2015): https://www.sqlbi.com/blog/marco/2015/02/24/use-firstnonblank-and-lastnonblank-instead-of-min-and-max-dax/