Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

The Power BI Data Visualization World Championships is back! Get ahead of the game and start preparing now! Learn more

Reply
alks_skla_f
Helper II
Helper II

Optimize big measure

Hello, I am trying to calculate how many business hours case was opened (excluded weekends and bank holidays)
I wrote a measure:

measure_FirstResolutionHours = 
VAR StartDate = [measure_StartDate]
VAR EndDate = [measure_EndDate]

-- Filter the TimeDim table for dates between StartDate and EndDate
VAR FilteredDates =
    FILTER(
        'TimeDim',
         DATEVALUE('TimeDim'[Date]) >= DATEVALUE(StartDate) &&
         DATEVALUE('TimeDim'[Date]) <= DATEVALUE(EndDate) &&
        //TimeDim[calculatedcolumn_test_ApacIsWorking]
        SWITCH(
            TRUE(),
            --If user chooses APAC, then filter by APAC work days
            SELECTEDVALUE(cps_sfdc_cases_history[region]) = "APAC", TimeDim[APAC Working Day] = "1",
            --If user chooses NALA, then filter by NALA work days
            SELECTEDVALUE(cps_sfdc_cases_history[region]) = "NALA", TimeDim[EMEA Working Day] = "1"
        --'TimeDim'[APAC Working Day] = "1" -- Only include working days
        )
    )

VAR StartWorkingHours = [measure_StartWorkingHours]
VAR EndWorkingHours = [measure_EndWorkingHours]

-- Calculate total seconds
VAR TotalSeconds =
    SUMX(
        -- For each date in the filtered table
        FilteredDates,
        VAR CurrentDate = 'TimeDim'[Date]
        VAR WorkSecondsPerDay =
            SWITCH(
                TRUE(),
                -- Case 1: Start and End are on the same day
                DATEVALUE(StartDate) = DATEVALUE(EndDate) && CurrentDate = DATEVALUE(StartDate),
                    MAX(0, MIN(
                        8, (MIN(EndWorkingHours, TIMEVALUE(EndDate)) - MAX(StartWorkingHours, TIMEVALUE(StartDate))) * 24 -- Difference in hours between StartDate and EndDate
                    )) * 3600, -- Clamp to 8 hours and convert to seconds

                -- Case 2: Current date is the start date
                CurrentDate = DATEVALUE(StartDate),
                    MAX(0, MIN(
                        8, 
                        (EndWorkingHours - TIMEVALUE(StartDate)) * 24 -- Remaining hours from start time to 17:00
                    )) * 3600, -- Clamp to 8 hours and convert to seconds

                -- Case 3: Current date is the end date
                CurrentDate = DATEVALUE(EndDate),
                    MAX(0, MIN(
                        8, 
                        (TIMEVALUE(EndDate) - StartWorkingHours) * 24 -- Hours from 9:00 to the end time
                    )) * 3600, -- Clamp to 8 hours and convert to seconds

                -- Case 4: All other dates (full workday)
                8 * 3600 -- Full 8-hour workday in seconds
            )
        RETURN
            WorkSecondsPerDay
    )

RETURN (DIVIDE(TotalSeconds, 3600))/8

How can I optimize this measure, please?

1 ACCEPTED SOLUTION
DataNinja777
Super User
Super User

Hi @alks_skla_f ,

 

The original measure is slow because it uses sumx to iterate through every single date between the Start and End dates. If a case is open for 100 days, the engine has to run the logic 100 times. 

You can optimize your measure like below using calculate:

measure_FirstResolutionHours_Optimized = 
VAR StartDate = [measure_StartDate]
VAR EndDate = [measure_EndDate]
VAR StartTime = TIMEVALUE(StartDate)
VAR EndTime = TIMEVALUE(EndDate)

-- Define Working Hours
VAR StartWorkHour = [measure_StartWorkingHours] 
VAR EndWorkHour = [measure_EndWorkingHours]     
VAR SecondsPerDay = (EndWorkHour - StartWorkHour) * 24 * 3600

-- Determine Region Logic
VAR IsAPAC = SELECTEDVALUE(cps_sfdc_cases_history[region]) = "APAC"
VAR IsNALA = SELECTEDVALUE(cps_sfdc_cases_history[region]) = "NALA"

-- 1. Calculate Total Working Days
-- This replaces SUMX. We count rows in the date table efficiently.
VAR WorkingDaysCount = 
    CALCULATE(
        COUNTROWS('TimeDim'),
        DATESBETWEEN('TimeDim'[Date], DATEVALUE(StartDate), DATEVALUE(EndDate)),
        KEEPFILTERS(
            SWITCH(
                TRUE(),
                IsAPAC, 'TimeDim'[APAC Working Day] = "1",
                IsNALA, 'TimeDim'[EMEA Working Day] = "1", 
                'TimeDim'[EMEA Working Day] = "1"
            )
        )
    )

-- 2. Check if specific Start/End dates are working days
-- This prevents subtracting time if the case started on a Sunday or Holiday
VAR StartDate_APAC_Flag = LOOKUPVALUE('TimeDim'[APAC Working Day], 'TimeDim'[Date], DATEVALUE(StartDate))
VAR StartDate_EMEA_Flag = LOOKUPVALUE('TimeDim'[EMEA Working Day], 'TimeDim'[Date], DATEVALUE(StartDate))
VAR EndDate_APAC_Flag   = LOOKUPVALUE('TimeDim'[APAC Working Day], 'TimeDim'[Date], DATEVALUE(EndDate))
VAR EndDate_EMEA_Flag   = LOOKUPVALUE('TimeDim'[EMEA Working Day], 'TimeDim'[Date], DATEVALUE(EndDate))

VAR IsStartDateWorking = 
    SWITCH(
        TRUE(),
        IsAPAC, StartDate_APAC_Flag = "1",
        IsNALA, StartDate_EMEA_Flag = "1",
        StartDate_EMEA_Flag = "1"
    )

VAR IsEndDateWorking = 
    SWITCH(
        TRUE(),
        IsAPAC, EndDate_APAC_Flag = "1",
        IsNALA, EndDate_EMEA_Flag = "1",
        EndDate_EMEA_Flag = "1"
    )

-- 3. Calculate Adjustments 
-- Only subtract "missed" morning hours if the start day was a working day
VAR StartAdjustment = 
    IF(
        IsStartDateWorking, 
        MAX(0, (StartTime - StartWorkHour) * 24 * 3600), 
        0
    )

-- Only subtract "missed" evening hours if the end day was a working day
VAR EndAdjustment = 
    IF(
        IsEndDateWorking, 
        MAX(0, (EndWorkHour - EndTime) * 24 * 3600),
        0
    )

-- 4. Final Calculation
VAR TotalSeconds = 
    IF(
        -- Edge Case: Start and End are on the same day
        DATEVALUE(StartDate) = DATEVALUE(EndDate),
        IF(
            IsStartDateWorking, -- Only count if it's a working day
            MAX(0, (MIN(EndWorkHour, EndTime) - MAX(StartWorkHour, StartTime)) * 24 * 3600),
            0 
        ),
        -- Standard Case: Multiple days
        -- Formula: (Total Days * 8h) - (Missed Morning Time) - (Missed Evening Time)
        (WorkingDaysCount * SecondsPerDay) - StartAdjustment - EndAdjustment
    )

RETURN 
    DIVIDE(TotalSeconds, 3600) / 8

The resultant output looks like below:

DataNinja777_0-1763482230129.png

I am attaching an example pbix file for your reference.

(This answer was written with the help of Gemini.)

 

Best regards,

 

 






 

View solution in original post

3 REPLIES 3
DataNinja777
Super User
Super User

Hi @alks_skla_f ,

 

The original measure is slow because it uses sumx to iterate through every single date between the Start and End dates. If a case is open for 100 days, the engine has to run the logic 100 times. 

You can optimize your measure like below using calculate:

measure_FirstResolutionHours_Optimized = 
VAR StartDate = [measure_StartDate]
VAR EndDate = [measure_EndDate]
VAR StartTime = TIMEVALUE(StartDate)
VAR EndTime = TIMEVALUE(EndDate)

-- Define Working Hours
VAR StartWorkHour = [measure_StartWorkingHours] 
VAR EndWorkHour = [measure_EndWorkingHours]     
VAR SecondsPerDay = (EndWorkHour - StartWorkHour) * 24 * 3600

-- Determine Region Logic
VAR IsAPAC = SELECTEDVALUE(cps_sfdc_cases_history[region]) = "APAC"
VAR IsNALA = SELECTEDVALUE(cps_sfdc_cases_history[region]) = "NALA"

-- 1. Calculate Total Working Days
-- This replaces SUMX. We count rows in the date table efficiently.
VAR WorkingDaysCount = 
    CALCULATE(
        COUNTROWS('TimeDim'),
        DATESBETWEEN('TimeDim'[Date], DATEVALUE(StartDate), DATEVALUE(EndDate)),
        KEEPFILTERS(
            SWITCH(
                TRUE(),
                IsAPAC, 'TimeDim'[APAC Working Day] = "1",
                IsNALA, 'TimeDim'[EMEA Working Day] = "1", 
                'TimeDim'[EMEA Working Day] = "1"
            )
        )
    )

-- 2. Check if specific Start/End dates are working days
-- This prevents subtracting time if the case started on a Sunday or Holiday
VAR StartDate_APAC_Flag = LOOKUPVALUE('TimeDim'[APAC Working Day], 'TimeDim'[Date], DATEVALUE(StartDate))
VAR StartDate_EMEA_Flag = LOOKUPVALUE('TimeDim'[EMEA Working Day], 'TimeDim'[Date], DATEVALUE(StartDate))
VAR EndDate_APAC_Flag   = LOOKUPVALUE('TimeDim'[APAC Working Day], 'TimeDim'[Date], DATEVALUE(EndDate))
VAR EndDate_EMEA_Flag   = LOOKUPVALUE('TimeDim'[EMEA Working Day], 'TimeDim'[Date], DATEVALUE(EndDate))

VAR IsStartDateWorking = 
    SWITCH(
        TRUE(),
        IsAPAC, StartDate_APAC_Flag = "1",
        IsNALA, StartDate_EMEA_Flag = "1",
        StartDate_EMEA_Flag = "1"
    )

VAR IsEndDateWorking = 
    SWITCH(
        TRUE(),
        IsAPAC, EndDate_APAC_Flag = "1",
        IsNALA, EndDate_EMEA_Flag = "1",
        EndDate_EMEA_Flag = "1"
    )

-- 3. Calculate Adjustments 
-- Only subtract "missed" morning hours if the start day was a working day
VAR StartAdjustment = 
    IF(
        IsStartDateWorking, 
        MAX(0, (StartTime - StartWorkHour) * 24 * 3600), 
        0
    )

-- Only subtract "missed" evening hours if the end day was a working day
VAR EndAdjustment = 
    IF(
        IsEndDateWorking, 
        MAX(0, (EndWorkHour - EndTime) * 24 * 3600),
        0
    )

-- 4. Final Calculation
VAR TotalSeconds = 
    IF(
        -- Edge Case: Start and End are on the same day
        DATEVALUE(StartDate) = DATEVALUE(EndDate),
        IF(
            IsStartDateWorking, -- Only count if it's a working day
            MAX(0, (MIN(EndWorkHour, EndTime) - MAX(StartWorkHour, StartTime)) * 24 * 3600),
            0 
        ),
        -- Standard Case: Multiple days
        -- Formula: (Total Days * 8h) - (Missed Morning Time) - (Missed Evening Time)
        (WorkingDaysCount * SecondsPerDay) - StartAdjustment - EndAdjustment
    )

RETURN 
    DIVIDE(TotalSeconds, 3600) / 8

The resultant output looks like below:

DataNinja777_0-1763482230129.png

I am attaching an example pbix file for your reference.

(This answer was written with the help of Gemini.)

 

Best regards,

 

 






 

Thank you very much! It works very quickly 🙂

amitchandak
Super User
Super User

@alks_skla_f , One of the ways to use networkdays and multiply by 8 
Business day with and without using DAX Function NETWORKDAYS: https://www.youtube.com/watch?v=Qs03ZZXXE_c
https://medium.com/@amitchandak/power-bi-dax-function-networkdays-5c8e4aca38c
Or refer 
https://exceleratorbi.com.au/calculating-business-hours-using-dax/

Share with Power BI Enthusiasts: Full Power BI Video (20 Hours) YouTube
Microsoft Fabric Series 60+ Videos YouTube
Microsoft Fabric Hindi End to End YouTube

Helpful resources

Announcements
Power BI DataViz World Championships

Power BI Dataviz World Championships

The Power BI Data Visualization World Championships is back! Get ahead of the game and start preparing now!

November Power BI Update Carousel

Power BI Monthly Update - November 2025

Check out the November 2025 Power BI update to learn about new features.

FabCon Atlanta 2026 carousel

FabCon Atlanta 2026

Join us at FabCon Atlanta, March 16-20, for the ultimate Fabric, Power BI, AI and SQL community-led event. Save $200 with code FABCOMM.