skip to content

In a Power BI matrix, why doesn't a DAX measure's total row equal the sum of the rows?

level: seniorimportance: should knowfreq 60%

answer

  1. the total is its own cell, not an addition
  2. a measure re-evaluates at every grain
  3. ask whether the measure is additive
  4. distinct counts and ratios behave differently
  5. one fix iterates the visible members

basics

~20 s

The total is not a sum of the displayed cells. Power BI evaluates the same DAX measure again in the total's filter context, with the row grouping removed, so any non-additive measure — a ratio, a distinct count, a conditional — legitimately returns something else.

solid answer

~50 s

A matrix does not add up the numbers you can see. Every cell, including the total row, is an independent evaluation of the measure in its own filter context; the total's context simply lacks the row-header filter. For an additive measure like `SUM(Sales[Amount])` that produces the same answer as adding the rows, which is why people assume summation is happening. For a non-additive measure it does not: a margin percentage recomputes globally, a `DISTINCTCOUNT` de-duplicates customers across all rows, and a measure containing `IF` or a threshold test re-evaluates that condition once at the total grain. None of that is a bug. If you want the total to be the sum of the per-row results, you must say so — typically `SUMX ( VALUES ( Product[Category] ), [Measure] )`, or branch on `ISINSCOPE` / `HASONEVALUE` to give the total row its own formula.

code

text · 6 lines
text
Category      Profit   Sales   Margin %   DistinctCustomers
Bikes           200k     1.0m     20.0%                1,200
Accessories      80k     200k     40.0%                  900
Clothing         30k     200k     15.0%                  700
---------------------------------------------------------------
Total           310k     1.4m     22.1%                2,100   <- not 75%, not 2,800

go deeper

for a junior

Recall that a measure is evaluated separately for every cell including the total, so ratios and counts can legitimately differ from the sum of the rows.

for a middle

Classify which measures break — ratios, distinct counts, conditionals — and explain what filter context the total row actually carries. Be able to write the SUMX over VALUES fix.

for a senior

Diagnose a reported wrong total end to end: decide whether the recomputed value is in fact correct, whether the problem is really a model or fan-out issue, and choose between explaining, iterating the grain, or blanking the total.

for a principal

Treat it as a trust problem: a total nobody can reconcile erodes confidence in the whole report, so set the convention for non-additive measures — naming, tooltips, suppressed totals — before the questions arrive from executives.

## Nothing is being summed The mental model that causes this question is that a visual computes cells and then adds them for the total. It does not. Power BI issues an evaluation of the measure per cell, each in the filter context that cell carries. The total row is one more cell whose context happens to omit the filter that the row header supplied. The measure has no idea it is "the total" and no access to the other cells' results. For an additive measure the arithmetic coincides. `SUM ( Sales[Amount] )` over all categories equals the sum of the per-category sums, because addition partitions cleanly. That coincidence trains everyone to expect summation, and then a ratio breaks it. ## The three families that break **Ratios.** `Margin % = DIVIDE ( [Profit], [Sales] )` at the total is total profit over total sales — the correct blended margin. Rows of 20%, 40% and 15% do not add to 75%, and nobody wants them to. Here the recomputed total is the *right* answer and the reader's expectation is the thing that is wrong; you fix it with formatting and labelling, not with DAX. **Distinct counts.** `DISTINCTCOUNT ( Sales[CustomerKey] )` per category counts customers within that category; the total counts distinct customers overall. A customer who bought in three categories is counted three times down the rows and once in the total, so the total is legitimately smaller. This one surprises business readers every time, and the honest answer is a footnote explaining that customers overlap. **Conditionals and thresholds.** `IF ( [Sales] > 100000, [Bonus], 0 )` evaluates the condition once at the total grain, where sales are large, so the total can pay a bonus even though every individual row failed the test — or the reverse. Same for `MAX`, `MIN`, ranking-based and "top N" logic. This family is where the total is genuinely misleading and DAX has to be changed. ## Making the total the sum of the rows When the per-row result really is the atom you want added, iterate the grain explicitly: ``` Bonus Total = SUMX ( VALUES ( Product[Category] ), [Bonus] ) ``` `VALUES ( Product[Category] )` returns the categories visible in the current filter context — one row per category on the total, a single row inside a category cell — and the measure reference triggers context transition, so `[Bonus]` is evaluated per category exactly as the row cells did. On a row cell the iteration has one member and the result is unchanged; on the total it is the sum you wanted. Note that this fixes the total *for that grain only*; a matrix with two nested levels needs the iteration to match whichever level is in scope. ## Branching on what is in scope The other tool is to detect the total explicitly. `ISINSCOPE ( Product[Category] )` returns TRUE when that column is grouping the current cell, so: ``` Bonus Display = IF ( ISINSCOPE ( Product[Category] ), [Bonus], SUMX ( VALUES ( Product[Category] ), [Bonus] ) ) ``` `HASONEVALUE ( Product[Category] )` is the older test and is nearly equivalent, but it also returns TRUE when a slicer happens to have narrowed the column to one member, which ISINSCOPE does not — that difference is what makes ISINSCOPE the safer choice for total detection. You can also return `BLANK()` at the total when no total is meaningful, which suppresses the number rather than showing a misleading one. ## Diagnosing it in the wild When someone reports a wrong total, the sequence is: identify whether the measure is additive; if it is, look for a duplicated or fanned-out relationship path rather than a total problem; if it is not, decide which of the three families it belongs to and whether the recomputed total is actually correct. Half the tickets close with an explanation and a tooltip. The other half close with a `SUMX ( VALUES ( … ) )` or an `ISINSCOPE` branch. ## What separates a senior answer A junior says "totals recompute". A senior says which measures recompute *differently*, names one case where the recomputed total is right and the expectation is wrong, gives the SUMX-over-VALUES fix with the grain caveat, and knows the ISINSCOPE-versus-HASONEVALUE distinction. It is a diagnosis question dressed as a trivia question.

  • Why is a DISTINCTCOUNT total smaller than the sum of the row values, and is that a bug?
    Not a bug. Each row counts distinct customers within that row's group; the total counts distinct customers across all groups, so anyone active in several groups is counted once instead of several times. The correct response is to label the measure clearly — 'distinct customers, non-additive' — rather than to force the total to add up, which would double-count real people.
  • How do ISINSCOPE and HASONEVALUE differ when detecting a total row?
    ISINSCOPE tests whether a column is actually grouping the current cell, so it is FALSE on a total even if a slicer narrowed that column. HASONEVALUE tests only that the column is filtered down to a single value, so a slicer picking one category makes it TRUE at the total row and your branch takes the wrong path. Prefer ISINSCOPE for total detection.
  • An additive measure like SUM shows a total larger than the sum of the visible rows. What now?
    That points away from total logic and towards the model. Usual causes are rows whose dimension key is missing or blank so they land in a hidden or blank-member group, a many-to-many or bi-directional path fanning rows out, or a visual-level filter or Top N applied to the rows but not the total. Check the blank member and the relationship path before touching DAX.

It is like asking each department for its own average salary and then asking the whole company for its average — the company number is a fresh calculation over everyone, not the average of the department averages.

saying these in an interview costs you the question

  • Assuming the visual sums the displayed cell values
  • Calling a recomputed ratio total a Power BI bug
  • Forcing a distinct-count total to add up, double-counting entities
  • Using HASONEVALUE for total detection where a slicer breaks it
  • Fixing the total by hard-coding a number in the measure

context