Hello! Welcome to the final lesson in our "Advanced DAX: Variables, Ranking, and Rolling Periods" module.
In our last session, you mastered the DATESINPERIOD function to create rolling totals, which are perfect for smoothing data over a fixed window like 90 days. We focused on how MAX('Date'[Date]) provides a dynamic anchor for that moving window.
Today, we'll build on that foundation to tackle a related but distinct concept: the running total (also known as a cumulative total). While a rolling total looks back over a fixed period (e.g., the last 90 days), a running total accumulates values from the very beginning of your data up to the current point in time. This is fundamental for tracking cumulative growth over the entire history of the dataset.
By the end of this lesson, you will be able to write a generic and robust running total measure that works over any date period.
1. Understanding the Running Total
Before we write any code, let's be crystal clear on what a running total is. It's a cumulative sum that grows over time. For each new date, you add that date's value to the sum of all the preceding dates.
This is different from the Year-to-Date (YTD) calculations you learned earlier, as a running total does not reset at the end of the year.

To see a quick demonstration of this concept and how it differs from a YTD calculation, please watch the first minute of the following video from SQLBI.
Computing a running total in DAX
This video, 'Computing a running total in DAX', clearly introduces the concept of a running total and contrasts it with YTD, explaining why we need to build our own custom measure.
Watch from the beginning to 00:55. Focus on the visual difference between the 'YTD' and the 'Running Total' columns in the chart.
2. The Core DAX Pattern for a Running Total
As the video mentions, the logic is to calculate our measure (e.g., Total Sales) for all dates that are less than or equal to the last date visible in the current filter context. This is where your understanding of CALCULATE and evaluation context becomes crucial.
Let's watch the rest of that video to see how this logic translates into a DAX measure.
Computing a running total in DAX
Continuing with the same video, the presenters now walk through the DAX code, explaining the function of each part of the formula.
Watch from 00:55 to the end (03:23). Pay close attention to how MAX, CALCULATE, and ALL work together to achieve the result.
The video demonstrates the classic pattern for a running total. Let's break it down, which aligns with your preference for understanding the theory before applying it.
Sales Running Total =
-- This measure calculates the cumulative sum of sales from the beginning of time
-- up to the last date visible in the current filter context.
VAR LastVisibleDate =
MAX ( 'Date'[Date] )
RETURN
CALCULATE (
[Total Sales],
'Date'[Date] <= LastVisibleDate,
ALL ( 'Date' )
)
Here's how it works:
VAR LastVisibleDate = MAX ( 'Date'[Date] ): Just as in our previous lesson, this variable captures the last date in the current filter context. In a table with daily granularity, this will be the date of the current row.CALCULATE ( [Total Sales], ... ): This begins the calculation, preparing to modify the context.ALL ( 'Date' ): This is a critical step. It acts as aCALCULATEmodifier that removes all existing filters from theDatetable. This is necessary because, without it, the filter context from the visual's row would only let us "see" the current date. We need to remove this filter so we can evaluate sales across all dates.'Date'[Date] <= LastVisibleDate: This is the new filter we apply. AfterALL('Date')has cleared the slate, this filter expression is evaluated. It tellsCALCULATEto consider all dates in the entireDatetable that are on or before ourLastVisibleDate.
This combination of removing the initial filter and then applying a new, broader filter is a powerful and common pattern in DAX.
3. Application and a More Robust Version
Now, it's time for you to apply this. Using the pattern above, create the Sales Running Total measure in your Power BI project. Add it to a table visual alongside your date and [Total Sales] measure to verify that it accumulates correctly.
Once you have the basic version working, we can enhance it. A common requirement in professional reports is to prevent the running total from appearing for future dates where no sales have occurred. The basic pattern will continue to show the last known total for all future dates in your Date table, which can be misleading.
The article below from DAX Patterns presents a more robust version of the formula that solves this exact problem.
Cumulative total – DAX Patterns
This article, 'Cumulative total', presents a production-ready pattern that includes a check to prevent the running total from displaying for future dates.
Read the 'Basic scenario' section. Focus on understanding the purpose of the LastDateWithSales variable and the IF statement that wraps the main calculation. This is a great example of defensive coding in DAX.
The enhanced pattern from the article introduces a "guard clause":
Sales Amount RT :=
VAR LastVisibleDate = MAX ( 'Date'[Date] )
VAR FirstVisibleDate = MIN ( 'Date'[Date] )
VAR LastDateWithSales =
CALCULATE (
MAX ( 'Sales'[Order Date] ),
REMOVEFILTERS () -- Modern equivalent of ALL()
)
VAR Result =
IF (
FirstVisibleDate <= LastDateWithSales,
CALCULATE (
[Sales Amount],
'Date'[Date] <= LastVisibleDate
)
)
RETURN
Result
The key addition is the IF statement. It checks if the period currently being evaluated in the visual (FirstVisibleDate) is before the very last date a sale was ever made (LastDateWithSales). If not, it returns a blank, which prevents the running total from populating into the future. This is an excellent technique for keeping your reports clean.
Finally, to reinforce the generic nature of this pattern, please review the text-based version of the video you watched. It not only recaps the date-based running total but also shows how the exact same logic can be applied to a non-date dimension, like customer categories.
Computing running totals in DAX - SQLBI
This SQLBI article provides a great summary and extends the running total concept beyond just dates, showcasing its versatility.
Read from 'The computation of the running total...' to the end of the 'RT Sales Customer Class' code block. Notice how the logic of <= CurrentValue and ALL(Dimension) is identical, whether the dimension is Date or Customer Class.
Conclusion
Congratulations on completing this module! You have now learned how to create both rolling totals and running totals—two of the most common and powerful analytical calculations in business intelligence.
Key Takeaways:
- A running total accumulates values from the beginning of time, unlike a rolling total (fixed window) or YTD (resets annually).
- The core DAX pattern for a running total is:
CALCULATE([Measure], 'Date'[Date] <= MAX('Date'[Date]), ALL('Date')). - The
ALL('Date')function is essential for removing the initial filter context so you can apply a new filter across all dates. - You can create more robust measures by adding guard clauses (e.g., using
IF) to handle edge cases, like preventing calculations from appearing for future dates. - This cumulative pattern is generic and can be applied to any sortable column, not just dates.
Preview of the Next Lesson:
In our next module, we will dive into creating more dynamic and interactive reports. We'll start by learning how to use the SELECTEDVALUE function to capture a user's selection from a slicer, allowing you to build measures that respond directly to user input.