This chapter covers DAX (Data Analysis Expressions) formulas and measures in Power BI, a critical topic for the DP-900 exam. DAX is the formula language used to create custom calculations in Power BI, and understanding it is essential for building effective data models. Approximately 15-20% of exam questions touch on analytics, including DAX basics. You will learn what measures are, how they differ from calculated columns, the core DAX functions (SUM, COUNT, AVERAGE, CALCULATE, FILTER, ALL, etc.), and how filter context drives dynamic calculations. This knowledge is fundamental for passing the DP-900 exam and for real-world Power BI development.
Jump to a section
Imagine you are a chef in a large kitchen with hundreds of ingredients stored in labeled bins (tables). Each bin has multiple compartments (columns) holding specific items like flour, sugar, or eggs. You need to create a custom dish (measure) that calculates the total calories of all ingredients used in a specific recipe. Instead of manually counting each ingredient every time, you write a 'recipe formula' (DAX measure) that tells your assistant (Power BI) how to combine the ingredients. The formula might say: 'For each recipe, sum the calories from all ingredients, but only include those that are fresh (filter context).' The assistant then goes to the bins, retrieves the relevant ingredients, performs the calculation, and presents the result. The key is that the assistant remembers the exact steps and can repeat them instantly for any recipe you select. If you change the recipe (slicer), the assistant recalculates automatically using the same formula, but only for the new set of ingredients. This is exactly how DAX measures work: they are reusable formulas that dynamically calculate values based on the current filter context, without storing the result in memory until needed. The filter context is like the recipe card that specifies which ingredients to include—it changes as you interact with your report.
What is DAX and Why Does It Exist?
DAX (Data Analysis Expressions) is a formula language introduced by Microsoft for Power BI, Analysis Services, and Power Pivot in Excel. It is designed to create custom calculations on tabular data models. Unlike Excel formulas that work on a cell-by-cell basis, DAX works on tables and columns, enabling powerful aggregations and dynamic calculations. The primary reason for DAX's existence is to allow business users to define complex business logic without writing traditional programming code. In the context of DP-900, you need to understand that DAX is used to create measures and calculated columns, but the exam focuses heavily on measures.
How DAX Works Internally
DAX operates on an in-memory columnar database engine called VertiPaq. When you write a DAX formula, it is compiled into a query plan that VertiPaq executes. The engine stores data compressed in columns, and DAX formulas leverage this structure for fast aggregations. A key concept is the filter context. When a measure is evaluated, the current filter context determines which rows from the underlying tables are included. For example, if a slicer filters by year 2023, the measure's SUM will only sum values from rows where the year is 2023. The filter context is automatically propagated through relationships. Another crucial concept is row context, which exists in calculated columns and iterator functions (like SUMX). In row context, the formula is evaluated for each row individually.
Key Components: Measures vs. Calculated Columns
Measures: Dynamic formulas that are evaluated at query time based on the current filter context. They do not consume storage space in the model; they are calculated on the fly. Measures are the preferred way to perform aggregations in Power BI. They appear in the Fields pane with a calculator icon.
Calculated Columns: Formulas that are evaluated at data refresh time and stored in the model. They consume memory and are computed once. Calculated columns are used when you need to add a new column to a table based on a row-by-row calculation (e.g., concatenating first and last name). On the DP-900 exam, know that measures are dynamic and calculated columns are static.
Core DAX Functions for DP-900
Aggregation Functions:
- SUM(<column>): Adds all values in a column. Only works with numeric columns.
- COUNT(<column>): Counts the number of non-blank values in a column.
- COUNTROWS(<table>): Counts the number of rows in a table.
- DISTINCTCOUNT(<column>): Counts the number of distinct values in a column.
- AVERAGE(<column>): Calculates the arithmetic mean of values in a column.
- MIN(<column>), MAX(<column>): Returns the smallest or largest value.
Logical Functions:
- IF(<logical_test>, <value_if_true>, <value_if_false>): Returns one of two values based on a condition.
- SWITCH(<expression>, <value1>, <result1>, ..., <else>): Evaluates an expression against multiple values.
Filter Functions:
- CALCULATE(<expression>, <filter1>, <filter2>, ...): Changes the filter context for the evaluation of an expression. This is the most important and powerful DAX function. It allows you to apply custom filters on top of the existing filter context.
- FILTER(<table>, <filter_expression>): Returns a table that is a subset of the original table based on a filter condition. Often used inside CALCULATE.
- ALL(<table>) or ALL(<column>): Removes all filters from the specified table or column. Used to create grand totals or override filter context.
- ALLSELECTED(<table>): Removes filters from the specified table but retains filters from slicers and other external filters.
- VALUES(<column>): Returns a one-column table of distinct values from a column, respecting the current filter context.
Time Intelligence Functions:
- TOTALYTD(<expression>, <dates>): Calculates the year-to-date value.
- SAMEPERIODLASTYEAR(<dates>): Returns a set of dates from the previous year.
- DATEADD(<dates>, <number_of_intervals>, <interval>): Shifts a set of dates by a specified number of intervals.
How Measures Interact with Relationships
When a measure is evaluated, Power BI automatically follows relationships between tables to propagate filters. For example, if you have a Sales table and a Date table linked by a date key, a slicer on Date[Year] will filter the Sales table through the relationship. Measures like SUM(Sales[Amount]) will only sum rows that match the selected year. This is called automatic cross-filtering. If you need to override this behavior, you use CALCULATE with filter functions or use the USERELATIONSHIP function to activate an inactive relationship.
Creating a Measure: Step-by-Step
1. In Power BI Desktop, go to the Report view. 2. Right-click on a table in the Fields pane and select 'New measure'. 3. Enter the DAX formula in the formula bar. For example:
Total Sales = SUM(Sales[Amount])Press Enter. The measure appears in the Fields pane with a calculator icon.
Use the measure in visuals like any other field.
Common DAX Patterns
Running Total:
Running Total =
CALCULATE(
SUM(Sales[Amount]),
FILTER(
ALL('Date'),
'Date'[Date] <= MAX('Date'[Date])
)
)This uses CALCULATE to sum sales for all dates up to the current date in the filter context.
Percentage of Grand Total:
% of Total Sales =
DIVIDE(
SUM(Sales[Amount]),
CALCULATE(
SUM(Sales[Amount]),
ALL(Sales)
)
)The ALL function removes filters from the Sales table, giving the total sales regardless of any slicers. DIVIDE handles division by zero gracefully.
Dynamic Grouping:
Sales Category =
SWITCH(
TRUE(),
[Total Sales] < 1000, "Low",
[Total Sales] < 5000, "Medium",
"High"
)This measure returns a category based on the total sales value in the current filter context.
Performance Considerations
Measures are generally fast because they are calculated in memory by VertiPaq.
Avoid using calculated columns when a measure can achieve the same result, as calculated columns increase model size.
Use DIVIDE instead of / to handle division by zero and improve performance.
Minimize the use of iterator functions like SUMX unless necessary, as they can be slower for large tables.
Use CALCULATE with simple filter conditions rather than complex FILTER expressions when possible.
How DAX Interacts with Power BI Visuals
When you drop a measure into a visual, Power BI automatically creates the appropriate filter context based on the visual's structure. For example, a bar chart with Category on the axis and a measure as the value will evaluate the measure for each category. The measure sees only the rows belonging to that category. If you add a slicer, it further restricts the filter context. Understanding this interaction is key to designing correct measures.
Identify the Business Requirement
Before writing any DAX, understand what calculation is needed. For example, 'total sales for the current year' or 'average order value per customer.' This determines whether you need a measure or a calculated column, and which DAX functions to use. Document the expected behavior under different filters.
Choose Measure vs. Calculated Column
If the calculation needs to be dynamic based on user interaction (slicers, filters, drill-down), it must be a measure. If the calculation is row-by-row and static (e.g., full name = first name + last name), use a calculated column. On the DP-900 exam, remember that measures are evaluated at query time and calculated columns at refresh time.
Write the DAX Formula
Use the formula bar in Power BI Desktop. Start with the function name, then provide arguments. For example: `Total Sales = SUM(Sales[Amount])`. Ensure correct syntax: function names are case-insensitive but column names must match exactly. Use square brackets for columns and measures. Use single quotes for table names if they contain spaces.
Test the Measure in a Visual
Add the measure to a visual (e.g., card, table, or chart). Interact with slicers and filters to verify that the measure updates correctly. Check edge cases: what happens when no data matches the filter? Should it return blank or zero? Use `COALESCE` or `IF` to handle blanks if needed.
Optimize Performance
If the measure is slow, review the formula. Avoid using `FILTER` on large tables when a simple filter argument in `CALCULATE` suffices. Use `DIVIDE` for safe division. Consider using `SUMX` only when row-by-row evaluation is necessary. Also, ensure relationships are properly defined to enable efficient filter propagation.
Scenario 1: Retail Sales Dashboard
A large retail chain uses Power BI to monitor daily sales across hundreds of stores. They need a measure that calculates 'Sales per Square Foot' dynamically by store, region, and time period. The DAX measure is:
Sales per Sq Ft = DIVIDE(SUM(Sales[Amount]), SUM(Stores[SquareFeet]))This measure works because the filter context from the visual (e.g., store name) automatically filters both the Sales and Stores tables through a relationship. However, a common misconfiguration is forgetting to establish a relationship between Sales and Stores on the StoreID column. Without it, the measure returns incorrect results because the filter does not propagate. In production, this dashboard is used by regional managers who slice by date and store. The measure must be efficient; using DIVIDE avoids division by zero errors. Performance is critical because the Sales table has millions of rows. The solution uses a star schema with a Date dimension, Store dimension, and Sales fact table.
Scenario 2: Financial Reporting with Time Intelligence
A finance department needs a report showing Year-over-Year (YoY) growth for revenue. They create a measure:
Revenue YoY % =
VAR CurrentRevenue = SUM(Revenue[Amount])
VAR PreviousRevenue = CALCULATE(SUM(Revenue[Amount]), SAMEPERIODLASTYEAR('Date'[Date]))
RETURN
DIVIDE(CurrentRevenue - PreviousRevenue, PreviousRevenue)This uses SAMEPERIODLASTYEAR which requires a properly marked date table. A common mistake is using a date column that is not contiguous or missing dates, causing the function to return incorrect results. In production, the date table must have a continuous range of dates with no gaps. The measure is used in a matrix visual with months on rows and years on columns. The filter context from the visual ensures that SAMEPERIODLASTYEAR returns the correct previous period. Misconfiguration often leads to blank values for months without prior year data.
Scenario 3: Dynamic Segmentation for Marketing
A marketing team wants to segment customers into tiers based on total purchases. They create a measure:
Customer Tier =
SWITCH(
TRUE(),
[Total Sales] > 10000, "Gold",
[Total Sales] > 5000, "Silver",
"Bronze"
)This measure is used in a visual that lists customers and their tier. However, because it is a measure, it is evaluated in the filter context of each customer row. If the visual includes a slicer for date, the tier changes dynamically. A common error is using a calculated column instead, which would freeze the tier at refresh time. In production, this measure is combined with a disconnected table to allow users to select a tier and see only those customers. The measure must be carefully tested because if the visual does not include a customer-level grain, the measure might aggregate incorrectly.
What DP-900 Tests on DAX
The DP-900 exam objective 3.4 covers 'Create and use DAX formulas and measures in Power BI.' Specifically, you need to:
Distinguish between measures and calculated columns.
Identify the purpose of common DAX functions: SUM, COUNT, AVERAGE, MIN, MAX, COUNTROWS, DISTINCTCOUNT, IF, SWITCH, CALCULATE, FILTER, ALL, ALLSELECTED, VALUES, and time intelligence functions (TOTALYTD, SAMEPERIODLASTYEAR, DATEADD).
Understand how filter context affects measures.
Recognize when to use a measure vs. a calculated column.
Common Wrong Answers and Why Candidates Choose Them
'Calculated columns are evaluated at query time' – This is false. Calculated columns are evaluated at data refresh time and stored. Candidates confuse them with measures. Remember: measures are dynamic, calculated columns are static.
'SUM function can be used on text columns' – False. SUM only works on numeric columns. COUNT works on any column. Candidates might think SUM is like Excel's SUM which can sum numbers stored as text, but DAX requires numeric data type.
'CALCULATE is used to create calculated columns' – False. CALCULATE is used in measures to modify filter context. Calculated columns use simple expressions without CALCULATE (though CALCULATE can be used in calculated columns, it's not typical and the exam focuses on measures).
'ALL function removes filters from all tables in the model' – False. ALL only removes filters from the specified table or column. Candidates think it's a global reset, but it's scoped.
Specific Numbers and Terms on the Exam
The exam expects you to know that DISTINCTCOUNT counts unique values.
COUNTROWS counts rows in a table, not column values.
DIVIDE is preferred over / for division because it handles division by zero.
Time intelligence functions require a date table marked as a date table with continuous dates.
The default behavior of relationships is to filter in one direction (single direction) unless bi-directional cross-filtering is enabled.
Edge Cases and Exceptions
When using ALL inside CALCULATE, it removes filters from the specified table but can be overridden by subsequent filter arguments.
FILTER returns a table and is often used inside CALCULATE, but it can be slow on large tables.
CALCULATE can accept multiple filter arguments; they are combined with AND logic.
If a measure references another measure, the filter context is preserved.
How to Eliminate Wrong Answers
For questions about measure vs. calculated column, ask: 'Is the result needed to be dynamic based on user interaction?' If yes, it's a measure.
For function purpose: match the function name to its description. SUM adds, COUNT counts non-blank, DISTINCTCOUNT counts distinct, etc.
For filter context: remember that slicers and visual filters create the filter context; CALCULATE can override it.
If a question mentions 'row-by-row calculation' and 'stored in the model,' it's a calculated column.
DAX is used to create measures and calculated columns in Power BI.
Measures are dynamic and evaluated at query time; calculated columns are static and evaluated at refresh time.
Key aggregation functions: SUM, COUNT, COUNTROWS, DISTINCTCOUNT, AVERAGE, MIN, MAX.
CALCULATE is the most important DAX function for modifying filter context.
ALL removes filters from a specified table or column; ALLSELECTED respects external slicers.
Time intelligence functions require a marked date table with continuous dates.
DIVIDE is preferred over / for safe division.
Filter context is automatically propagated through relationships.
These come up on the exam all the time. Here's how to tell them apart.
Measures
Evaluated at query time
Do not consume storage
Dynamic based on filter context
Used for aggregations and complex calculations
Appear with a calculator icon in Fields pane
Calculated Columns
Evaluated at data refresh time
Consume storage in the model
Static and computed once
Used for row-by-row operations (e.g., concatenation)
Appear with a column icon in Fields pane
Mistake
Measures are stored in the model and consume memory.
Correct
Measures are not stored; they are calculated at query time. Only calculated columns consume storage. Measures appear in the Fields pane but are essentially saved formulas.
Mistake
CALCULATE can only be used with measures.
Correct
CALCULATE can be used with any expression that returns a scalar value, including SUM, COUNT, or even another measure. It modifies the filter context for that expression.
Mistake
ALL function removes all filters from the entire data model.
Correct
ALL removes filters only from the specified table or column. To remove filters from multiple tables, you must call ALL on each table separately.
Mistake
SUM and SUMX are interchangeable.
Correct
SUM adds all values in a single column without row context. SUMX iterates over a table and evaluates an expression for each row, then sums the results. They are not interchangeable; SUMX is needed for row-by-row calculations.
Mistake
Time intelligence functions work with any date column.
Correct
Time intelligence functions require a date table that is marked as a date table (with continuous, non-repeating dates) and that has a relationship to the fact table. Using a random date column will produce incorrect results.
Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.
A measure is a dynamic formula calculated at query time based on the current filter context. It does not consume storage. A calculated column is computed at data refresh time and stored in the model, consuming memory. Measures are used for aggregations and dynamic calculations; calculated columns are used for row-by-row operations like combining text. On the DP-900 exam, remember that measures appear with a calculator icon and calculated columns with a column icon.
Filter context is the set of filters applied to a measure at evaluation time. It comes from slicers, visual filters, report filters, and drill-down actions. When a measure is used in a visual, Power BI automatically restricts the data to the relevant subset. For example, if a slicer selects '2023', the measure SUM(Sales[Amount]) will only sum sales from 2023. CALCULATE can modify the filter context by adding or overriding filters.
CALCULATE changes the filter context for an expression. It takes an expression (like SUM) and one or more filter arguments. For example, `CALCULATE(SUM(Sales[Amount]), Sales[Year] = 2023)` sums sales only for 2023, regardless of other filters. It is the most powerful DAX function because it allows you to dynamically adjust filters within a measure.
DIVIDE is safer because it handles division by zero gracefully. If the denominator is zero, DIVIDE returns BLANK (or an optional alternate result), whereas the / operator would return an error. For example, `DIVIDE(SUM(Sales[Amount]), SUM(Sales[Quantity]))` returns BLANK if quantity is zero, avoiding errors in visuals.
Time intelligence functions like TOTALYTD, SAMEPERIODLASTYEAR, and DATEADD allow you to perform calculations over time periods. They require a date table marked as a date table with continuous dates. For example, `TOTALYTD(SUM(Sales[Amount]), 'Date'[Date])` returns the year-to-date sum. These functions automatically respect the filter context and shift dates accordingly.
Yes, measures can reference other measures. For example, `Profit = [Total Sales] - [Total Cost]` is valid. The filter context is automatically passed to the referenced measures. This is a common practice to build modular calculations.
SUM adds all values in a single column. SUMX iterates over a table and evaluates an expression for each row, then sums the results. For example, `SUMX(Sales, Sales[Quantity] * Sales[Price])` computes row-level amounts and sums them. Use SUM when you have a pre-calculated column; use SUMX when you need to compute an expression row by row.
You've just covered DAX Formulas and Measures in Power BI — now see how well it sticks with free DP-900 practice questions. Full explanations included, no account needed.
Done with this chapter?