Wednesday, January 21, 2026

Does Calendar-Primarily based Time-Intelligence Change Customized Logic?


Introduction

calendar-based Time Intelligence, the necessity for customized Time Intelligence logic has decreased dramatically.

Now, we will create customized calendars to satisfy our Time Intelligence calculation wants.

You might need learn my article about superior Time Intelligence:

https://towardsdatascience.com/advanced-time-intelligence-in-dax-with-performance-in-mind/

Many of the customized logic is now not wanted.

However we nonetheless have eventualities the place we should have customized calculations, like working common.

A while in the past, SQLBI wrote an article about calculating the working common.

This piece makes use of the identical rules described there in a barely totally different method.

Let’s see how we will calculate the working common over three months by utilizing the brand new Calendars.

Utilizing traditional Time Intelligence

First, we use the usual Gregorian calendar with the traditional Time Intelligence date desk.

I take advantage of an analogous method as described within the SQLBI article linked within the References part under.

Operating Common by Month = 
// 1. Get the primary and final Date for the present Filter Context
VAR MaxDate = MAX( 'Date'[Date] )


// 2. Generate the Date vary wanted for the Shifting common (three months)
VAR  DateRange =
 DATESINPERIOD( 'Date'[Date]
        ,MaxDate
        ,-3
        ,MONTH
    )

// 3. Generate a desk filtered by the Date Vary generated at step 2
// This desk comprises solely three rows
VAR SalesByMonth = 
    CALCULATETABLE(
        SUMMARIZECOLUMNS(
            'Date'[MonthKey]
            , "#Gross sales", [Sum Online Sales]
            
        )
        ,DateRange
    )

RETURN
    // 4. Calculate the Common over the three values within the desk generate in step 3
    AVERAGEX(SalesByMonth, [#Sales])

When executing this measure in DAX Studio, I get the anticipated outcomes:

Determine 1 – Operating Common over three months with the traditional Time Intelligence method (Determine by the Writer)

To this point, so good.

Utilizing a regular calendar

Subsequent, I created a Calendar named “Gregorian Calendar” and adjusted the code to make use of this calendar.

To make this simpler to know, I copied the date desk to a brand new desk named “Gregorian Date Desk”.

The change is when calling the DATESINPERIOD() operate.

As an alternative of utilizing the date column, I take advantage of the newly created calendar:

Operating Common by Month = 
// 1. Get the primary and final Date for the present Filter Context
VAR MaxDate = MAX( 'Gregorian Date Desk'[Date] )


// 2. Generate the Date vary wanted for the Shifting common (three months)
VAR  DateRange =
 DATESINPERIOD( 'Gregorian Calendar'
        ,MaxDate
        ,-3
        ,MONTH
    )



// 3. Generate a desk filtered by the Date Vary generated at step 2
// This desk comprises solely three rows
VAR SalesByMonth = 
    CALCULATETABLE(
        SUMMARIZECOLUMNS(
            'Gregorian Date Desk'[MonthKey]
            , "#Gross sales", [Sum Online Sales]
            
        )
        ,DateRange
    )

RETURN
    // 4. Calculate the Common over the three values within the desk generate in step 3
    AVERAGEX(SalesByMonth, [#Sales])

As anticipated, the outcomes are similar:

Determine 2 – Identical End result as earlier than when utilizing the Calendar (Determine by the Writer)

The efficiency is superb, as this question completes in 150 milliseconds.

Utilizing a customized calendar

However what occurs when utilizing a customized calendar?

For instance, a calendar with 15 months per 12 months and 31 days for every month?

I created such a calendar for my article, which describes use circumstances for calendar-based Time Intelligence (See the Hyperlink on the High and within the References part).

If you have a look at the code for the measure, you’ll discover that it’s totally different:

Operating Common by Month (Customized) = 
    VAR LastSelDate = MAX('Monetary Calendar'[CalendarEndOfMonthDate])

    VAR MaxDateID = CALCULATE(MAX('Monetary Calendar'[ID_Date])
                                ,REMOVEFILTERS('Monetary Calendar')
                                ,'Monetary Calendar'[CalendarEndOfMonthDate] = LastSelDate
                                )

    VAR MinDateID = CALCULATE(MIN('Monetary Calendar'[ID_Date])
                                ,REMOVEFILTERS('Monetary Calendar')
                                ,'Monetary Calendar'[CalendarEndOfMonthDate] = EOMONTH(LastSelDate, -2)
                                )

    VAR SalesByMonth = 
        CALCULATETABLE(
            SUMMARIZECOLUMNS(
                'Monetary Calendar'[CalendarYearMonth]
                , "#Gross sales", [Sum Online Sales]
                
            )
            ,'Monetary Calendar'[ID_Date] >= MinDateID
                && 'Monetary Calendar'[ID_Date] <= MaxDateID
        )

    RETURN
    AVERAGEX(SalesByMonth, [#Sales])

The explanation for the modifications is that this desk lacks a date column usable with the DATESINPERIOD() operate. Because of this, I need to use customized code to calculate the worth vary for ID_Date.

These are the outcomes:

Determine 3 – Outcomes of the working common when utilizing a customized calendar with no Dates (Determine by the Writer)

As you’ll be able to verify, the outcomes are right.

Optimizing by utilizing a day index

However once I analyze the efficiency, it’s not that nice.

It takes nearly half a second to calculate the outcomes.

We will enhance efficiency by eradicating the necessity to retrieve the minimal and most ID_Date and performing a extra environment friendly calculation.

I do know that every month has 31 days.

To return three months, I do know that I need to return by 93 days.

I can use this to create a sooner model of the measure:

Operating Common by Month (Monetary) = 
    // Step 1: Get the final Month (ID)
    VAR SelMonth = MAX('Monetary Calendar'[ID_Month])
    
    // Step 2: Generate the Date Vary from the final 93 days
    VAR DateRange =
        TOPN(93
        ,CALCULATETABLE(
                    SUMMARIZECOLUMNS('Monetary Calendar'[ID_Date])
                    ,REMOVEFILTERS('Monetary Calendar')
                    ,'Monetary Calendar'[ID_Month] <= SelMonth
                )
                ,'Monetary Calendar'[ID_Date], DESC
            )
    
    
    // 3. Generate a desk filtered by the Date Vary generated at step 2
    // This desk comprises solely three rows
    VAR SalesByMonth = 
        CALCULATETABLE(
            SUMMARIZECOLUMNS(
                'Monetary Calendar'[ID_Month]
                , "#Gross sales", [Sum Online Sales]
                
            )
            ,DateRange
        )
    
    RETURN
        // 4. Calculate the Common over the three values within the desk generate in step 3
        AVERAGEX(SalesByMonth, [#Sales])

This time, I used the TOPN() operate to retrieve the 93 earlier rows from the Monetary Calendar desk and used this checklist as a filter.

The outcomes are similar to the earlier model:

Determine 4 – Outcomes of the Model which makes use of the final 93 days (Determine by the Writer)

This model wants solely 118 ms to finish.

However can we go even additional with the optimization?

Subsequent, I added a brand new column to the Fiscal Calendar to assign ranks to the rows. Now, every date has a singular quantity which is in direct correlation to the order of them:

Determine 5 – Extract from the Monetary Calendar desk with the RowRank column (Determine by the Writer)

The measure utilizing this column is the next:

Operating Common by Month (Monetary) = 
    // Step 1: Get the final Month (ID)
    VAR MaxDateRank = MAX('Monetary Calendar'[ID_Date_RowRank])
    
    // Step 2: Generate the Date Vary from the final 93 days
    VAR DateRange =
            CALCULATETABLE(
                        SUMMARIZECOLUMNS('Monetary Calendar'[ID_Date])
                        ,REMOVEFILTERS('Monetary Calendar')
                        ,'Monetary Calendar'[ID_Date_RowRank] <= MaxDateRank
                            && 'Monetary Calendar'[ID_Date_RowRank] >= MaxDateRank - 92
                    )
                    --ORDER BY 'Monetary Calendar'[ID_Date] DESC
    
    
    // 3. Generate a desk filtered by the Date Vary generated at step 2
    // This desk comprises solely three rows
    VAR SalesByMonth = 
        CALCULATETABLE(
            SUMMARIZECOLUMNS(
                'Monetary Calendar'[ID_Month]
                , "#Gross sales", [Sum Online Sales]
                
            )
            ,DateRange
        )
    
    RETURN
        // 4. Calculate the Common over the three values within the desk generate in step 3
        AVERAGEX(SalesByMonth, [#Sales])

The outcome is identical, I don’t present it once more.

However right here is the comparability from the execution statistics:

Determine 6 – Execution statistics of the 2 Measures. On high, you see the statistics for the one utilizing TOPN(). Under are the statistics for the one utilizing the RowRank column (Determine by the Writer)

As you’ll be able to see, the Model utilizing TOPN() is barely slower than the one utilizing the RowRank column.

However the variations are marginal.

Extra importantly, the model utilizing the RowRank column requires extra information to finish the calculations. See the Rows column for particulars.

This implies extra RAM utilization.

However with this small variety of rows, the variations are nonetheless marginal.

It’s your selection which model you like.

Utilizing a weekly calendar

Lastly, let’s have a look at a week-based calculation.

This time, I need to calculate the rolling common during the last three weeks.

Because the calendar-based Time Intelligence permits for the creation of a week-based calendar, the measure is similar to the second:

Operating Common by Week = 
// 1. Get the primary and final Date for the present Filter Context
VAR MaxDate = MAX( 'Gregorian Date Desk'[Date] )


// 2. Generate the Date vary wanted for the Shifting common (three months)
VAR  DateRange =
 DATESINPERIOD( 'Week Calendar'
        ,MaxDate
        ,-3
        ,WEEK
    )



// 3. Generate a desk filtered by the Date Vary generated at step 2
// This desk comprises solely three rows
VAR SalesByMonth = 
    CALCULATETABLE(
        SUMMARIZECOLUMNS(
            'Gregorian Date Desk'[WeekKey]
            , "#Gross sales", [Sum Online Sales]
            
        )
        ,DateRange
    )

RETURN
    // 4. Calculate the Common over the three values within the desk generate in step 3
    AVERAGEX(SalesByMonth, [#Sales])

The important thing half is that I take advantage of the “WEEK” parameter within the DATESINPERIOD() name.
That’s all.

That is the results of the question:

Determine 7 – End result for the working common over three weeks (Determine by the Writer)

The efficiency is superb, with execution occasions under 100 ms.

Bear in mind that weekly calculations are solely doable with the calendar-based Time Intelligence.

Conclusion

As you’ve gotten seen, the calendar-based Time Intelligence makes life simpler with customized logic: we solely have to move the calendar as an alternative of a date column to the capabilities. And we will calculate weekly intervals.

However the present characteristic set doesn’t embody a semester interval. Once we should calculate semester-based outcomes, we should both use traditional Time Intelligence or write customized code.

However we nonetheless want customized logic, particularly after we don’t have a date column in our calendar desk. In such circumstances, we will’t use the usual time intelligence capabilities, as they nonetheless work with date columns.

Bear in mind: An important activity when working with calendar-based Time Intelligence is constructing a constant and full calendar desk. From my expertise, that is probably the most advanced activity.

As a sidenote, I discovered some attention-grabbing capabilities on daxlib.org a couple of working common.

I added a hyperlink to the capabilities within the References part under.

These capabilities observe a totally totally different sample, however I needed to incorporate them to create an entire image of this subject.

References

The talked about SQLBI.com article on calculating the working Common:

https://www.sqlbi.com/articles/rolling-12-months-average-in-dax

Time Collection capabilities on daxlib.org with a distinct method:

https://daxlib.org/package deal/TimeSeries.MovingAverage

Right here is my final article, the place I clarify Calendar-based Time-Intelligence:

https://towardsdatascience.com/use-cases-for-the-new-calendar-based-time-intelligence/

Like in my earlier articles, I take advantage of the Contoso pattern dataset. You possibly can obtain the ContosoRetailDW Dataset free of charge from Microsoft right here.

The Contoso Knowledge can be utilized freely underneath the MIT License, as described on this doc. I modified the dataset to shift the information to modern dates.

Related Articles

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Latest Articles

PHP Code Snippets Powered By : XYZScripts.com