COUNT를 쓰다가 “참/거짓 열은 지원하지 않는다”는 안내를 만나면 자연스럽게 찾게 되는 함수가 COUNTA입니다. 이름이 비슷해서 그냥 넘어가기 쉬운데, 어디가 같고 어디가 다른지 한 번 정리해 두면 개수 함수 고르는 일이 훨씬 편해집니다. 이 글에서는 COUNTA의 동작과 빈 문자열이라는 함정, 그리고 실무에서 자주 맞닥뜨리는 세 가지 상황(연락처 확보율, 조건부 개수, 참/거짓 열)을 같은 데이터로 살펴보겠습니다.
문법과 반환값
COUNTA( <열> )
인수는 열 하나이고, 그 열에서 비어 있지 않은 행의 수를 정수로 돌려줍니다. 세어볼 행이 하나도 없으면 0이 아니라 빈 값(BLANK)이 반환됩니다. Microsoft 문서가 설명하는 COUNT와의 가장 큰 차이는 한 줄입니다. COUNTA는 참/거짓(Boolean) 형식을 지원합니다. COUNT 자체는 COUNT 함수 글에서 정리했습니다.
Power BI Desktop에서 측정값으로 만들기
메뉴 이름은 Power BI 버전과 언어 설정에 따라 조금 다를 수 있다는 점을 먼저 말씀드립니다. 일반적인 순서는 이렇습니다.
- 보고서 보기에서 오른쪽 필드 창의 테이블(예: 회원)을 선택합니다.
- 상단 리본에서 “새 측정값”(영문판은 New measure)을 누릅니다.
- 수식 입력줄에
이메일개수 = COUNTA( 회원[이메일] )처럼 이름과 식을 적고 Enter를 누릅니다. - 만든 측정값을 카드 시각화에 올려 값을 확인하고, 상태 같은 열과 함께 표에 올려 줄마다 어떻게 나뉘는지 봅니다.
예제 데이터
설명하려고 만든 가상 회원 표입니다. 이메일이 없는 회원, 전화번호 칸에 빈 문자열이 들어간 회원, 전화번호가 완전히 비어 있는 회원을 일부러 섞었습니다. 결과는 Power BI에서 돌린 화면이 아니라 직접 세어서 적은 값이니, 같은 식을 본인 데이터에 적용해서 확인해 보세요.
| 회원 | 이메일 | 전화번호 | 마케팅동의 | 상태 |
|---|---|---|---|---|
| 1 | a@example.com | 010-1111 | TRUE | 활성 |
| 2 | (빈 값) | 010-2222 | FALSE | 활성 |
| 3 | c@example.com | “” (빈 문자열) | TRUE | 휴면 |
| 4 | d@example.com | (빈 값) | FALSE | 활성 |
| 5 | (빈 값) | 010-5555 | TRUE | 휴면 |
열마다 세어 보기
이메일개수 = COUNTA( 회원[이메일] )
이메일이 있는 회원은 1, 3, 4번이라 3입니다.
동의열개수 = COUNTA( 회원[마케팅동의] )
참/거짓 열이라서 COUNT로는 셀 수 없고, COUNTA로는 모든 행에 값이 있으니 5입니다. 여기서 주의할 점이 있습니다. 이 5는 “동의한 사람 수”가 아니라 “동의 여부가 기록된 행 수”입니다. 이 구분은 시나리오 3에서 다시 다룹니다.
빈 문자열은 센다
전화번호개수 = COUNTA( 회원[전화번호] )
결과는 4입니다. 1번, 2번, 5번의 전화번호에 3번의 빈 문자열이 더해진 값입니다. DAX Guide에 따르면 COUNTA는 진짜 빈 값(BLANK)은 세지 않지만 빈 문자열(“”)은 센다고 합니다. 화면에서는 3번과 4번 칸이 똑같이 비어 보이지만 집계에서는 다르게 취급됩니다. Microsoft 문서의 개념 설명에서도 BLANK는 데이터베이스의 null을 대신하는 별도의 값 형식이고, 빈 문자열과는 다른 값입니다.
실무 시나리오 1: 연락처 확보율
마케팅 담당자가 “이메일과 전화번호를 확보한 비율”을 묻는다고 해 보겠습니다. 이메일부터 구합니다.
이메일확보율 =
DIVIDE( COUNTA( 회원[이메일] ), COUNTROWS( 회원 ) )
3 ÷ 5 = 60%입니다. 전체 회원 수 자리에는 COUNTROWS를 썼습니다. 열 값의 유무와 상관없이 테이블의 행 수를 세는 함수이기 때문입니다. 같은 방식으로 전화번호 확보율을 구하면 이렇습니다.
전화번호확보율_순진한식 =
DIVIDE( COUNTA( 회원[전화번호] ), COUNTROWS( 회원 ) )
4 ÷ 5 = 80%가 나오는데, 실제로 번호가 적혀 있는 회원은 1번, 2번, 5번 세 명뿐이니 맞는 값은 60%입니다. 3번의 빈 문자열이 “값이 있는 행”으로 세어졌기 때문입니다. 번호가 실제로 적힌 회원만 세려면 길이를 확인하는 조건이 필요합니다.
전화번호입력회원 =
CALCULATE(
COUNTROWS( 회원 ),
LEN( 회원[전화번호] ) > 0
)
빈 값과 빈 문자열 모두 길이가 0이라서 걸러지고, 1, 2, 5번만 남아 3이 됩니다. 확보율은 3 ÷ 5 = 60%입니다. 이렇게 열을 그냥 COUNTA로 세면 “입력 칸이 있는 행”과 “내용이 있는 행”이 달라질 수 있다는 점을 기억해 두세요.
실무 시나리오 2: 조건과 함께 세기 (COUNTAX)
“활성 회원 중 이메일이 있는 회원 수”는 두 가지 방법으로 셀 수 있습니다. 하나는 CALCULATE로 조건을 바꾸는 방식입니다.
활성이메일회원 =
CALCULATE(
COUNTA( 회원[이메일] ),
회원[상태] = "활성"
)
활성 회원은 1, 2, 4번이고 이 중 이메일이 있는 회원은 1번과 4번이라 결과는 2입니다. CALCULATE가 조건을 바꾸는 원리는 CALCULATE 함수 글에 정리해 두었습니다. 다른 하나는 반복 함수인 COUNTAX입니다. Microsoft 문서의 예제도 “상태가 활성인 거래처로 먼저 걸러낸 표에서 전화번호가 있는 행을 센다”는 구조입니다.
활성이메일회원_AX =
COUNTAX(
FILTER( 회원, 회원[상태] = "활성" ),
회원[이메일]
)
결과는 같은 2입니다. DAX Guide에 따르면 COUNTA는 내부적으로 COUNTAX를 실행하는 것과 같고 성능 차이는 없습니다. 열 하나를 세는 일이면 COUNTA와 CALCULATE의 조합이 읽기 쉽고, 세는 대상이 계산식의 결과라면 COUNTAX를 쓰는 편이 자연스럽습니다.
COUNTAX에는 Microsoft 문서가 따로 알려주는 주의점이 있습니다. 식의 결과가 빈 문자열이면 그 결과는 비어 있지 않은 값으로 세어진다는 것입니다. 예를 들어 이메일에 빈 문자열을 이어 붙이는 식을 세면, 원래 비어 있던 이메일도 문자열 결합 결과(빈 문자열)가 되어 세어질 수 있습니다.
이메일_결합후개수 =
COUNTAX( 회원, 회원[이메일] & "" )
문서의 규칙대로라면 이 식은 모든 행이 세어져 5가 되어야 합니다. 다만 이 부분은 제가 Power BI에서 직접 돌려 확인한 것이 아니라 문서의 설명을 따라 적은 것이므로, 쓰시는 환경에서 결과를 직접 확인해 보시길 권합니다. 핵심은 “식의 결과가 빈 값인지 빈 문자열인지에 따라 개수가 달라진다”는 점입니다.
실무 시나리오 3: 참/거짓 열의 응답률과 동의율
마케팅 동의 열은 참/거짓 형식이라 COUNT로는 셀 수 없습니다. 먼저 “동의 여부가 기록된 비율”은 이렇게 구합니다.
동의기록률 =
DIVIDE( COUNTA( 회원[마케팅동의] ), COUNTROWS( 회원 ) )
5 ÷ 5 = 100%입니다. 모든 회원에게 동의 여부가 기록되어 있다는 뜻일 뿐, 동의한 사람의 비율은 아닙니다. 동의율은 참인 행만 따로 세어야 합니다.
동의율 =
DIVIDE(
CALCULATE( COUNTROWS( 회원 ), 회원[마케팅동의] = TRUE() ),
COUNTROWS( 회원 )
)
참인 회원은 1, 3, 5번이라 3 ÷ 5 = 60%입니다. 보고서에 “동의 100%”라고 잘못 적는 일이 생기지 않으려면 어떤 비율인지 이름을 분명히 붙이는 것이 좋습니다.
COUNT와 무엇이 같고 다른가
| 구분 | COUNT | COUNTA |
|---|---|---|
| 숫자, 날짜, 문자열 열 | 값이 있는 행을 센다 | 같은 결과 |
| 참/거짓 열 | 지원하지 않음 | 값이 있는 행을 센다 |
| 빈 값 | 세지 않음 | 세지 않음 |
| 빈 문자열 | 센다 | 센다 |
DAX Guide는 참/거짓이 아닌 열에서는 두 함수가 완전히 같은 결과를 낸다고 정리합니다. 그러니 COUNT를 쓸 수 있는 열이라면 굳이 COUNTA로 바꿀 이유는 없고, 열 형식이 참/거짓일 때만 COUNTA를 고르면 됩니다. 반복 함수 쪽도 같은 관계입니다. DAX Guide에 따르면 COUNTX와 COUNTAX는 참/거짓 형식을 빼면 같고, COUNTAX는 참/거짓도 처리합니다.
내부 동작과 성능
DAX Guide의 설명으로는 COUNTA는 내부적으로 COUNTAX를 실행하는 것과 같고, 둘 사이에 성능 차이는 없다고 합니다. 행 수 자체를 세려는 목적이라면 특정 열의 값 유무에 영향을 받지 않는 COUNTROWS가 더 알맞습니다. Microsoft는 COUNT 대신 COUNTROWS를 쓰라는 모범 사례 문서를 따로 두고 있고, 이유로 효율, 빈 값에 대한 영향 없음, 의도가 분명함을 듭니다. 같은 이유가 COUNTA에도 대부분 해당합니다.
쓰지 말아야 할 때
- 테이블의 전체 행 수가 필요할 때: 열이 비어 있는 행이 빠지므로 COUNTROWS를 쓰세요.
- “참인 건수”가 필요할 때: COUNTA는 값이 기록된 행을 셀 뿐입니다. 조건을 걸어야 합니다.
- 서로 다른 값의 수가 필요할 때: 중복도 모두 세어집니다. DISTINCTCOUNT가 맞습니다.
- 빈 문자열을 빈 값처럼 취급하고 싶을 때: 길이를 확인하는 조건을 함께 쓰세요.
알아둘 점
- 인수는 열 하나뿐입니다. 테이블은 넣을 수 없습니다.
- 센 행이 없으면 빈 값이 반환됩니다. 0으로 보이게 하고 싶다면 별도 처리가 필요하며, 0을 더하는 방식은 데이터가 없는 항목까지 0으로 표시되는 부작용이 있다고 SQLBI가 설명합니다.
- DirectQuery 모드에서는 계산 열이나 행 수준 보안 규칙 안에서 쓸 수 없다고 Microsoft 문서에 적혀 있습니다. 측정값에서는 쓸 수 있습니다.
- 지역 설정에 따라 인수 구분자가 쉼표 대신 세미콜론일 수 있습니다. 식을 붙여 넣었는데 오류가 난다면 먼저 확인해 보세요.
자주 하는 실수
- 참/거짓 열 개수를 “참인 행 수”로 착각: COUNTA는 값이 기록된 행을 셀 뿐, 참만 세지 않습니다.
- 빈 칸이 전부 같다고 생각: 빈 값과 빈 문자열은 다르게 집계됩니다.
- 행 수를 세려고 아무 열이나 COUNTA: 그 열이 빈 행은 빠집니다.
- “확보율”을 COUNTA로만 계산: 빈 문자열 때문에 실제보다 높게 나올 수 있습니다.
정리
COUNTA는 “비어 있지 않은 값의 수”를 세는 함수이고, COUNT와의 차이는 참/거짓 열 지원 하나입니다. 빈 문자열은 값으로 세어진다는 점, 참/거짓 열에서 얻은 개수가 참의 개수가 아니라는 점, 그리고 비율을 구할 때 분모를 COUNTROWS로 잡아야 한다는 점만 기억해 두세요. 예제는 가상 데이터이니 본인 모델의 열 이름으로 바꿔 직접 확인해 보시고, 동작은 버전에 따라 다를 수 있어 공식 문서도 함께 보시길 권합니다.
참고한 자료
- Microsoft Learn, COUNTA function (DAX): https://learn.microsoft.com/en-us/dax/counta-function-dax
- Microsoft Learn, COUNTAX function (DAX): https://learn.microsoft.com/en-us/dax/countax-function-dax
- Microsoft Learn, DAX overview: https://learn.microsoft.com/en-us/dax/dax-overview
- DAX Guide, COUNTA: https://dax.guide/counta/
- DAX Guide, COUNTAX: https://dax.guide/countax/
- SQLBI, How to return 0 instead of BLANK in DAX: https://www.sqlbi.com/articles/how-to-return-0-instead-of-blank-in-dax/