Measures, not columns
What a measure is, why it beats a calculated column for totals, and the filter context that decides its number.
A measure is a formula that Power BI works out at the moment a visual asks for it, for exactly the slice of data that visual shows. That one idea explains most of DAX, and most of the numbers that come out wrong.
Column or measure?
Use a measure for anything you add up, average or count, and a calculated column for the things you slice by. A column is worked out once per row and stored, so it costs memory on every row. A measure is worked out only when a visual shows it, for the rows in view.
A calculated column is worked out once per row, when the model refreshes, and stored:
Line Total = Sales[Quantity] * Sales[Price]A measure is worked out when it is used, over whatever rows are in view:
Total Sales = SUMX ( Sales, Sales[Quantity] * Sales[Price] )Both give the same total in a card. The column costs memory on every row of the table, forever; the measure costs nothing until it is shown. Keep columns for things you slice by, like a price band or a customer group.
The first measures
On the Sales table, select New measure and add these one at a time:
Total Sales = SUM ( Sales[Amount] )Orders = DISTINCTCOUNT ( Sales[OrderID] )Average Order = DIVIDE ( [Total Sales], [Orders] )DIVIDE returns blank instead of an error when there are no orders, so an empty month shows nothing rather than a broken visual. And Average Order uses the other two measures by name: each number is defined once and reused.
Filter context
Put Total Sales in a table visual with the product categories as rows. Each row shows a different number, but the formula is the same. What changes is the filter context: for each row, Power BI filters the Sales table to that category first, then works out the measure.
Everything that filters a visual adds to that context: its rows and columns, the slicers on the page, the filters on the page and the report, and the relationships that carry a filter from one table to the next. A measure never knows which visual it is in; it only sees the rows the filter context leaves.
Make them easy to use
- Give each measure a format (currency, whole number, percentage) once, in the measure's properties, instead of in every visual.
- Write a description. It shows when someone hovers over the measure in the field list.
- Hide the raw number columns, like
Sales[Amount], so report builders use the measures and not their own sums.