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
sjrrkb123
Helper III
Helper III

Capacity Calculation

Suppose I have two tables,
Table 1: Dates with Calendar Date, isWeekday, isHoliday
Table 2: Professionals with Professional Name, start date, end date

I am trying to calculate capacity using date values in a slicer (Calendar Date) to make these dynamic with a measure. Here is the measure I have made:

 

IT Total Days Worked v2 = 
var start_end = 
    CALCULATE(COUNTROWS('Dates - Dim Dates'),
        DATESBETWEEN('Dates - Dim Dates'[CalendarDate],[IT Employment Start Date],[IT Employment End Date]),
        KEEPFILTERS('Dates - Dim Dates'[IsWeekDay] = TRUE()),
        KEEPFILTERS('Dates - Dim Dates'[IsHoliday] = FALSE()))
var start_only = 
    CALCULATE(COUNTROWS('Dates - Dim Dates'),
        DATESBETWEEN('Dates - Dim Dates'[CalendarDate],[IT Employment Start Date],MAX('Dates - Dim Dates'[CalendarDate])),
        KEEPFILTERS('Dates - Dim Dates'[IsWeekDay] = TRUE()),
        KEEPFILTERS('Dates - Dim Dates'[IsHoliday] = FALSE()))
var between = 
    CALCULATE(COUNTROWS('Dates - Dim Dates'),
        KEEPFILTERS('Dates - Dim Dates'[IsWeekDay] = TRUE()),
        KEEPFILTERS('Dates - Dim Dates'[IsHoliday] = FALSE()))
var min_end = 
    CALCULATE(COUNTROWS('Dates - Dim Dates'),
        DATESBETWEEN('Dates - Dim Dates'[CalendarDate],MIN('Dates - Dim Dates'[CalendarDate]),[IT Employment End Date]),
        KEEPFILTERS('Dates - Dim Dates'[IsWeekDay] = TRUE()),
        KEEPFILTERS('Dates - Dim Dates'[IsHoliday] = FALSE()))
var start_date = [IT Employment Start Date]
var end_date = [IT Employment End Date]
var active = [IT Active Flag]
var last_cal_date = [Last Calendar Date]
var first_cal_date = [First Calendar Date]
var holiday_ratio = 343/365

RETURN
IF(NOT(active), 
    IF(start_date <= first_cal_date && end_date >=last_cal_date, between,
    IF(start_date <= first_cal_date && end_date < last_cal_date, min_end,
    IF(start_date > first_cal_date && end_date < last_cal_date, start_end,
    IF(start_date > first_cal_date && end_date >= last_cal_date, start_only)))),
    IF(start_date <= first_cal_date, between, 
    IF(start_date > first_cal_date, start_only))) * holiday_ratio

 

My problem is this is very slow. I suspect it is using row based calculation rather than set based calculations in SQL server. However, I am at a loss of how to make this faster and was hoping to find suggestions here.

1 ACCEPTED SOLUTION
TomMartens
Super User
Super User

Hey @sjrrkb123 ,

 

the task you are facing has a name, it's called events-in-progress. This article provides anything you need:

https://blog.gbrueckl.at/events-in-progress/

This article contains all the relevant links.

Make sure that you read this article first: 

http://sqljason.com/2012/11/classifying-and-solving-events-in.html

 

For quite some time I pursue a different approach, by creating an additional table based on the information of the employee table DateStart and DateEnd. This table contains a single row for each employee, each day.
From my experience, it does not matter if this table contains millions of rows, even 10s of millions is no problem 🙂 My largest "expanded" table currently contains ~200millions rows. All measures will become more simple and for this - much more faster.
Here is a screenshot of my final data model:

TomMartens_0-1595389014728.png

 

This is my employee table:

image.png

I use this DAX statement to create the new table:

 

EmployeeIsActive = 
var CalendarEnddate = MAX('Calendar'[Date])
return
ADDCOLUMNS(
    GENERATE(
        'Employee'
        , var EmployeeEndDate = 'Employee'[DateEnd]
        var SeriesEndDate = IF(ISBLANK(EmployeeEndDate) , CalendarEnddate , EmployeeEndDate)
        return
        GENERATESERIES('Employee'[DateStart] , SeriesEndDate , 1)
    )
    , "simpleValue" , 1
)

 

 

If there is no EndDate in the EmployeeTable I replace the empty value with the max calendar date.
This example is a little simplified, for this, I do not rename the column Value, that is automatically created by the GENERATESERIES function.
I create 1-to-many relationships with the new table on the many side of the relationships.

Now I can create more simple measures e.g. a DISTINCTCOUNT of the employee id from the new table. I "just" have to consider how I have to treat EndDates that are not on the end date of a month, but this is comparatively simple.

A simple screenshot with a DISTINCTCOUNT of the EmployeeID from the new table, for this simple example no complex measure is needed.

image.png

Hopefully, this will help to tackle your challenge.

Regards,
Tom



Did I answer your question? Mark my post as a solution, this will help others!

Proud to be a Super User!
I accept Kudos 😉
Hamburg, Germany

View solution in original post

3 REPLIES 3
sjrrkb123
Helper III
Helper III

@TomMartens Thank you very much for the info and the links. I ended up not using your approach and changed my calculation to drastically simplify my DAX. It accounts for both the start/end dates of employees and the dynamic slider values for my use case. Here is what I did:

 

Total Businee Days Worked = 
var between = 
    SUMX(Professionals,
        CALCULATE(COUNTROWS('Dates - Dim Dates'),
            'Dates - Dim Dates'[IsWeekDay] = TRUE(),
            'Dates - Dim Dates'[IsHoliday] = FALSE(),
            DATESBETWEEN('Dates - Dim Dates'[CalendarDate], [Most Recent Hire Date], [Employment End Date]),
            DATESBETWEEN('Dates - Dim Dates'[CalendarDate], [First Calendar Date], [Last Calendar Date]),
            USERELATIONSHIP(Ticket[SUBMITTER_ID], Professionals[ID])))
var start_date = [Most Recent Hire Date]
RETURN
IF(ISBLANK(start_date), 0, between)

        

 

TomMartens
Super User
Super User

Hey @sjrrkb123 ,

 

the task you are facing has a name, it's called events-in-progress. This article provides anything you need:

https://blog.gbrueckl.at/events-in-progress/

This article contains all the relevant links.

Make sure that you read this article first: 

http://sqljason.com/2012/11/classifying-and-solving-events-in.html

 

For quite some time I pursue a different approach, by creating an additional table based on the information of the employee table DateStart and DateEnd. This table contains a single row for each employee, each day.
From my experience, it does not matter if this table contains millions of rows, even 10s of millions is no problem 🙂 My largest "expanded" table currently contains ~200millions rows. All measures will become more simple and for this - much more faster.
Here is a screenshot of my final data model:

TomMartens_0-1595389014728.png

 

This is my employee table:

image.png

I use this DAX statement to create the new table:

 

EmployeeIsActive = 
var CalendarEnddate = MAX('Calendar'[Date])
return
ADDCOLUMNS(
    GENERATE(
        'Employee'
        , var EmployeeEndDate = 'Employee'[DateEnd]
        var SeriesEndDate = IF(ISBLANK(EmployeeEndDate) , CalendarEnddate , EmployeeEndDate)
        return
        GENERATESERIES('Employee'[DateStart] , SeriesEndDate , 1)
    )
    , "simpleValue" , 1
)

 

 

If there is no EndDate in the EmployeeTable I replace the empty value with the max calendar date.
This example is a little simplified, for this, I do not rename the column Value, that is automatically created by the GENERATESERIES function.
I create 1-to-many relationships with the new table on the many side of the relationships.

Now I can create more simple measures e.g. a DISTINCTCOUNT of the employee id from the new table. I "just" have to consider how I have to treat EndDates that are not on the end date of a month, but this is comparatively simple.

A simple screenshot with a DISTINCTCOUNT of the EmployeeID from the new table, for this simple example no complex measure is needed.

image.png

Hopefully, this will help to tackle your challenge.

Regards,
Tom



Did I answer your question? Mark my post as a solution, this will help others!

Proud to be a Super User!
I accept Kudos 😉
Hamburg, Germany

@TomMartens this is great...I will look into applying this tomorrow and get back to you. 

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!

December 2025 Power BI Update Carousel

Power BI Monthly Update - December 2025

Check out the December 2025 Power BI Holiday Recap!

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.