Join us at FabCon Atlanta from March 16 - 20, 2026, for the ultimate Fabric, Power BI, AI and SQL community-led event. Save $200 with code FABCOMM.
Register now!The Power BI Data Visualization World Championships is back! Get ahead of the game and start preparing now! Learn more
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.
Solved! Go to Solution.
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:
This is my employee table:
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.
Hopefully, this will help to tackle your challenge.
Regards,
Tom
@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)
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:
This is my employee table:
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.
Hopefully, this will help to tackle your challenge.
Regards,
Tom
@TomMartens this is great...I will look into applying this tomorrow and get back to you.
The Power BI Data Visualization World Championships is back! Get ahead of the game and start preparing now!
| User | Count |
|---|---|
| 39 | |
| 37 | |
| 33 | |
| 32 | |
| 29 |
| User | Count |
|---|---|
| 133 | |
| 88 | |
| 85 | |
| 68 | |
| 64 |