COUNT vs COUNTX in DAX: Understanding Counting Functions
In this article, we will learn how to use COUNT and COUNTX in DAX to count values in a table. We will also understand an important difference between counting an existing column and counting the result of an expression.
📥 Practice Data:
Download Practice Data Free
🎥 Prefer learning through video?
DAX YouTube Playlist
What Are COUNT and COUNTX in DAX?
COUNT and COUNTX are DAX counting functions, but they work differently.
COUNT counts the non-blank values in a specified column, while COUNTX evaluates an expression row by row and counts the non-blank results.
| Function | How it works |
|---|---|
| COUNT | Counts non-blank values directly from a column. |
| COUNTX | Iterates through a table, evaluates an expression for each row, and counts the non-blank results. |
1. COUNT Function
The first query uses COUNT to count values from three different columns in the AvgTable table.
Query
EVALUATE
ROW(
"Col A", COUNT(AvgTable[Col A]),
"Col B", COUNT(AvgTable[Col B]),
"Col C", COUNT(AvgTable[Col C])
)
Step-by-step explanation
Step 1: EVALUATE
EVALUATE returns the result of the table expression. In this query, the table expression is created using ROW.
Step 2: ROW
ROW creates a single-row table containing the results of the expressions provided inside it.
Step 3: COUNT(AvgTable[Col A])
The COUNT function counts the non-blank values present in AvgTable[Col A].
Step 4: COUNT(AvgTable[Col B])
Similarly, COUNT counts the non-blank values in AvgTable[Col B].
Step 5: COUNT(AvgTable[Col C])
This counts the non-blank values in AvgTable[Col C].
What will you get?
The query returns one row with three calculated values.
The exact numbers depend on the data available in your AvgTable.
| Col A | Col B | Col C |
|---|---|---|
| Count of non-blank values | Count of non-blank values | Count of non-blank values |
COUNT directly counts non-blank values from a column. It does not require a table iterator.
2. COUNTX Function
Now let us look at COUNTX. Unlike COUNT, COUNTX takes a table and an expression. It evaluates that expression for each row and counts the non-blank results.
Query
EVALUATE
ROW(
"Col C", COUNTX(AvgTable, COALESCE([Col C], 0))
)
Step-by-step explanation
Step 1: EVALUATE
EVALUATE returns the result of the table expression created by ROW.
Step 2: ROW
ROW creates a single-row result and gives the calculated value the output name Col C.
Step 3: COUNTX(AvgTable, …)
COUNTX iterates through the rows of AvgTable. For every row, it evaluates the expression provided as its second argument.
Step 4: COALESCE([Col C], 0)
COALESCE returns the value of [Col C] when it is not blank. If [Col C] is blank, it returns 0.
Step 5: COUNTX counts the expression results
Because the expression uses COALESCE to replace blank values with 0, the expression produces a numeric result instead of a blank for those rows. Therefore, those rows are also counted by COUNTX.
This is a key difference from directly counting AvgTable[Col C]. With COUNTX, you are counting the result of the expression COALESCE([Col C], 0), not simply counting the original column values.
Understanding the expression
COALESCE([Col C], 0)
The expression can be understood as follows:
- If [Col C] contains a value, return that value.
- If [Col C] is blank, return 0.
- COUNTX then counts the non-blank results produced by this expression.
COUNT vs COUNTX
| Feature | COUNT | COUNTX |
|---|---|---|
| Input | A column | A table and an expression |
| Evaluation | Counts values directly from the column | Evaluates an expression row by row |
| Blank handling | Blank column values are not counted | Depends on the result of the expression |
| Iterator | No | Yes |
| Example | COUNT(AvgTable[Col C]) | COUNTX(AvgTable, COALESCE([Col C], 0)) |
Why Does COALESCE Matter in COUNTX?
Consider a row where [Col C] is blank.
With a direct count such as COUNT(AvgTable[Col C]), that blank value is not counted.
But in the COUNTX query, the expression converts the blank value into 0:
COALESCE([Col C], 0)
The result is no longer blank. It is 0, and COUNTX counts that non-blank expression result.
When using an iterator such as COUNTX, always pay attention to the expression being evaluated. Functions such as COALESCE can change whether a row produces a blank or non-blank result.
Understanding the Two Queries Together
COUNT(AvgTable[Col C])
Here, DAX directly examines AvgTable[Col C] and counts its non-blank values.
COUNTX(
AvgTable,
COALESCE([Col C], 0)
)
Here, DAX goes through AvgTable row by row, evaluates COALESCE([Col C], 0) for every row, and then counts the non-blank expression results.
📝 Practice Exercise
Using the same AvgTable, try creating a query that compares the following:
- COUNT(AvgTable[Col C])
- COUNTX(AvgTable, COALESCE([Col C], 0))
Observe whether the two counts are the same or different when Col C contains blank values.
Then experiment with another expression inside COUNTX and observe how the result changes.
Conclusion
In this article, we learned how COUNT and COUNTX work in DAX.
- COUNT counts non-blank values directly from a column.
- COUNTX iterates through a table and counts the non-blank results of an expression.
- COALESCE can replace blank values with 0.
- Because COUNTX counts the expression result, replacing blanks with zero can cause those rows to be counted.
- The choice between COUNT and COUNTX depends on whether you need to count a column directly or count the result of a row-by-row expression.
Understanding the difference between aggregation functions such as COUNT and iterator functions such as COUNTX is an important foundation for writing more advanced DAX queries.
📥 Practice Data:
Download Practice Data Free
🎥 Prefer learning through video?
DAX YouTube Playlist