100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
Programming

Time Intelligence in DAX

Time intelligence functions like TOTALYTD, SAMEPERIODLASTYEAR, and DATEADD let DAX measures compare and accumulate values across calendar periods.

DAXIntermediate10 min readJul 10, 2026
Analogies

Why Time Intelligence Needs a Date Table

Every DAX time intelligence function, including TOTALYTD, SAMEPERIODLASTYEAR, and DATEADD, requires a dedicated Date table containing one contiguous row per calendar day spanning the full range of the fact data, connected to the fact table through a one-to-many relationship on a date key column. This Date table must be explicitly marked as a date table in Power BI Desktop's modeling settings, which validates that its date column is unique and contiguous, because time intelligence functions internally rely on being able to walk backward and forward through consecutive days without gaps.

🏏

Cricket analogy: A Date table needing every single day represented is like a Test match scorecard needing every ball of every over logged in sequence, since a gap in the ball-by-ball record would break any 'run rate over the last 10 overs' calculation.

Common Time Intelligence Functions

TOTALYTD(SUM(Sales[Amount]), 'Date'[Date]) accumulates a measure from the start of the fiscal or calendar year up through the last date in the current filter context, while SAMEPERIODLASTYEAR('Date'[Date]) shifts the entire current date filter back exactly one year, and DATEADD('Date'[Date], -1, MONTH) shifts it back by an arbitrary number of periods, making it more flexible for comparisons like month-over-month. PREVIOUSMONTH and PREVIOUSYEAR are shorthand functions that return the full prior calendar month or year regardless of what date range is currently selected.

🏏

Cricket analogy: TOTALYTD accumulating from the start of the year is like a batsman's season aggregate that keeps climbing with every innings played from opening day through today's match.

dax
Total Sales YTD =
TOTALYTD(
    SUM(Sales[Amount]),
    'Date'[Date]
)

Sales Last Year =
CALCULATE(
    SUM(Sales[Amount]),
    SAMEPERIODLASTYEAR('Date'[Date])
)

YoY Growth % =
DIVIDE(
    [Total Sales] - [Sales Last Year],
    [Sales Last Year]
)

Comparing Periods: Year-over-Year Growth

A year-over-year growth measure typically combines CALCULATE with SAMEPERIODLASTYEAR to compute last year's figure, such as Sales LY := CALCULATE(SUM(Sales[Amount]), SAMEPERIODLASTYEAR('Date'[Date])), and then wraps the difference in DIVIDE to compute a safe percentage: YoY Growth % := DIVIDE([Total Sales] - [Sales LY], [Sales LY]). Using DIVIDE here instead of a plain slash operator prevents an error or infinite result when Sales LY is zero or blank, such as for a product that launched only this year.

🏏

Cricket analogy: Comparing this season's average to last season's using SAMEPERIODLASTYEAR is like a commentator pulling up a batsman's exact same-stage-of-season stats from last year for a direct year-over-year comparison.

Pitfalls with Time Intelligence

A Date table with missing dates, such as one built only from distinct dates that appear in the Sales fact table rather than a fully generated calendar, silently breaks time intelligence functions because SAMEPERIODLASTYEAR and DATEADD assume a continuous sequence of days to walk through. Organizations with a fiscal year that doesn't align to the calendar year, such as one starting in July, must also set the year-end date parameter inside functions like TOTALYTD, for example TOTALYTD([Total Sales], 'Date'[Date], "06/30"), or time intelligence will silently calculate against a January 1st fiscal boundary instead.

🏏

Cricket analogy: A Date table missing gaps is like a scorebook that only logs days a match was actually played, silently breaking a 'form over the last 30 days' calculation whenever there's a rest day in between fixtures.

Time intelligence functions silently produce wrong or blank results if the Date table isn't marked as a date table in Modeling settings, or if it's missing calendar days — always build the Date table with CALENDAR() or CALENDARAUTO() covering every day in the fact data's range, and mark it explicitly.

  • Time intelligence functions require a dedicated, contiguous Date table with one row per calendar day.
  • The Date table must be marked as a date table in Power BI Desktop's modeling settings.
  • TOTALYTD accumulates a measure from the start of the year through the current filter's latest date.
  • SAMEPERIODLASTYEAR shifts the current date filter back exactly one year.
  • DATEADD shifts the date filter by an arbitrary number of periods, useful for month-over-month comparisons.
  • Combine CALCULATE with SAMEPERIODLASTYEAR and DIVIDE to build a safe year-over-year growth measure.
  • Non-calendar fiscal years require an explicit year-end parameter in functions like TOTALYTD.

Practice what you learned

Was this page helpful?

Topics covered

#Programming#PowerBIStudyNotes#TimeIntelligenceInDAX#Time#Intelligence#DAX#Needs#StudyNotes#SkillVeris#ExamPrep