Start free
Back to blog

SUM vs SUMX in DAX: When Each Returns the Wrong Total

A paper machine comparing direct stack aggregation with row-by-row transformation on a carousel

Use SUM when you need to add one stored numeric column. Use SUMX when you must iterate a table, evaluate an expression for each row, and then add those results. Choosing the wrong iterator grain—not the function name itself—is what most often creates a plausible but incorrect total.

The basic difference

SUM accepts a column:

Total Quantity =
SUM ( Sales[Quantity] )

SUMX accepts a table and an expression:

Gross Sales =
SUMX (
    Sales,
    Sales[Quantity] * Sales[Unit Price]
)

For each visible Sales row, SUMX multiplies Quantity by Unit Price and adds the row results. The SUMX reference describes it as an iterator.

If the model already contains a trustworthy Sales[Gross Amount] column at the same grain, this may be equivalent:

Gross Sales =
SUM ( Sales[Gross Amount] )

Neither formula is automatically better. The correct choice depends on where the business logic belongs, whether the stored column is authoritative, and the grain of the table being summed.

When SUM is the right choice

Prefer SUM for an additive column whose row values already represent the thing you need:

  • quantity sold;
  • transaction amount;
  • cost amount;
  • hours worked; or
  • another numeric fact at the table’s grain.
Total Cost =
SUM ( Sales[Cost Amount] )

The current filter context determines which Sales rows are visible. SUM adds the values; it does not create a new row context.

When SUMX is necessary

Use SUMX when each row needs an expression:

Net Line Value =
SUMX (
    Sales,
    Sales[Quantity] * Sales[Unit Price] * ( 1 - Sales[Discount Rate] )
)

The calculation must happen per Sales row because Quantity, Unit Price, and Discount Rate can differ by row. Multiplying aggregated values would answer a different question:

-- Usually wrong
SUM ( Sales[Quantity] )
    * AVERAGE ( Sales[Unit Price] )
    * ( 1 - AVERAGE ( Sales[Discount Rate] ) )

That shortcut loses the pairing between each row’s quantity, price, and discount.

The classic average-price trap

Suppose one unit sells for 100 and nine units sell for 10. The simple average of the two price rows is 55, but the weighted average selling price is 19.

Average Selling Price =
DIVIDE (
    SUMX ( Sales, Sales[Quantity] * Sales[Unit Price] ),
    SUM ( Sales[Quantity] )
)

The numerator evaluates value at line grain. The denominator counts units. AVERAGE(Sales[Unit Price]) gives every row equal weight, not every unit.

SUMX does not mean “fix my total”

When a total looks wrong, developers often wrap the measure in:

SUMX ( VALUES ( Product[Category] ), [Some Measure] )

This forces the total to add category-level results. It is correct only if the business rule is explicitly additive by Category.

Consider margin percentage:

Margin % =
DIVIDE ( [Margin], [Total Sales] )

The grand total should divide total Margin by total Sales. Summing category percentages is meaningless, and even averaging them gives each category equal weight regardless of size.

Before adding an iterator, write this sentence:

Evaluate the expression once per ___, then add those results.

If you cannot fill the blank with a defensible business grain, SUMX is probably masking the problem.

Measure references and context transition

Inside an iterator, a measure reference is evaluated for the current iterator row:

Sales From Products Over 10K =
SUMX (
    FILTER (
        VALUES ( Product[ProductKey] ),
        [Total Sales] > 10000
    ),
    [Total Sales]
)

The expression is evaluated once per visible ProductKey. Iterating Category would apply the threshold to categories instead. The formulas can both parse and return numbers, but the grain changes the business definition.

This is where row context and filter context meet: the iterator creates a row context, and the measure reference uses context transition to evaluate for that row.

Performance considerations

SUM over a stored column is usually simple for the storage engine. SUMX can also perform well, especially for straightforward expressions, but complex iterations over large tables can require more formula-engine work.

Do not denormalize or add calculated columns solely from a rule of thumb. First:

  1. make the measure correct;
  2. test on representative data;
  3. inspect the query with a profiler such as DAX Studio; and
  4. optimize the actual bottleneck.

A five-case test

Test any SUM or SUMX measure under:

  1. one hand-calculable row;
  2. multiple rows with different values;
  3. a filtered category;
  4. the grand total; and
  5. an empty context.

Record the expected result before running the measure. For multiplication, include rows with different quantities and prices so an aggregate shortcut cannot pass by accident.

Decision checklist

Use SUM when:

  • one numeric column already stores the additive value;
  • the column grain matches the calculation; and
  • no per-row expression is required.

Use SUMX when:

  • the calculation combines columns per row;
  • a measure must be evaluated once per entity;
  • weighting matters; or
  • the business rule explicitly defines an iteration grain.

The question is not “Which function fixes the total?” It is “At what grain must this expression be evaluated?” Put that reasoning into practice with the DAX exercises and solutions or open a DAX Solver challenge.

Done reading?

Put it into reps — pick a challenge.

Start practicing More posts