Eliminating repetitive Storage Engine queries in Power BI - powerbi

Please see the Power BI model file attached here. I have an Activity table and I'd like to plot on a Line chart, the number of users that were active in the last 365 days as on the date of X Axis.
Hence, I created a date table, but it is not related as the purpose of this table is only to use in the X Axis or date filtering, and all metrics are calculated for the 365 days prior to the date of calculation.
The below DAX formula works, but if analysed in DAX Studio, there is one storage engine query for every date in the X Axis. This is really slow in my actual model file and I am looking for help optimising it.
Active Users =
var latestDate = MAX('Calendar'[Date])
RETURN
CALCULATE(
DISTINCTCOUNT('Activity Details'[Group User ID]),
ALL('Calendar'[Date]),
'Activity Details'[Event Date] <= latestDate,
'Activity Details'[Event Date] >= (latestDate - 365)
)
EDIT
The following DAX formula queries storage engine only once, but spends way more time in formula engine.
Active Users =
var latestDate = MAX('Calendar'[Date])
RETURN
CALCULATE(
SUMX(
SUMMARIZE(
'Activity Details', 'Activity Details'[Group User ID],
"Last Event", MAX('Activity Details'[Event Date])
),
1
),
ALL('Calendar'[Date]),
'Activity Details'[Event Date] <= latestDate,
'Activity Details'[Event Date] >= (latestDate - 365)
)

Related

How can I lock a measure in PBI?

Im working on a dashboard in PBI and I have the next problem...
I have a card that only have to show the month data. For this I use this measure:
Month Orders = CALCULATE(
DISTINCTCOUNT( 'Data'[ORDER] ),FILTER('Data',
'Data'[Month] = 'Data'[Actual Month]),
ALL('Data Incidentes')
)
I understand that if I use All() filter on a measure, this measure don't change when I apply a visual filter but in my case this change.
So my problem is that I have the card that show the month orders but when i apply a visual filter this data change and I don't want it to change.
I hope you understand my problem and my english jaja.
Month Orders = CALCULATE(
DISTINCTCOUNT( 'Data'[ORDER] ),FILTER('Data',
'Data'[Month] = 'Data'[Actual Month]),
ALL('Data Incidentes')
)
Can you try this instead-
Month Orders =
CALCULATE(
DISTINCTCOUNT( 'Data'[ORDER] ),
FILTER(
ALL('Data'),
'Data'[Month] = 'Data'[Actual Month]
)
)

Dax Counts at end of each month

I have a measure that depending on a "before" date slicer shows how many accounts were active at any given point in the company's history. I'm being asked to show month over month growth (end of month 1 compared to end of month 2 totals) but that's difficult given my measure needs a date slicer with one date value to return a total.
Active_Accounts =
CALCULATE (
COUNTX (
FILTER (
VALUES ( 'TEST CHARGES'[BI_ACCT] ),
[total as of date] > 0
),
[BI_ACCT]
)
)
link to sample file
https://www.dropbox.com/s/pewpm85wogvq3xf/test%20active%20charges.pbix?dl=0
if you move the slider you'll see the active accounts total change to show at that time in history how many accounts had an active charge. What I'm hoping to add to the dashboard is a measure that can be placed on a table of month end values and show the active accounts at that time so I can do month to month comparisons.
Active Accounts =
var month_end =
ENDOFMONTH (
LASTNONBLANK (
'Test Charges Date Table'[Date],
CALCULATE ( DISTINCTCOUNT( ( 'TEST CHARGES'[BI_ACCT] ) )
)
)
)
var last_date =
CALCULATE(
LASTNONBLANK('TEST CHARGES'[CHG_DATE], ""),
'TEST CHARGES'[CHG_DATE] <= max('Test Charges Date Table'[Date])
)
var num_of_actives =
CALCULATE(
Countx(
Filter(
Values('TEST CHARGES'[BI_ACCT]),
[total as of date] > 0
) , [BI_ACCT]
),
last_date <= month_end
)
return num_of_actives
As Peter advices you do not need Calculate() to show total in the card and using of Calculate() reduces speed of calculation. In your case speed is reduced with no reason.
There are no need to have a special column for month - use date hierarchy for row and just exclude day and quater levels.
Then add the measure to the visual table/matrix
Cummulative Count =
Calculate(
[Active_Accounts]
,'Test Charges Date Table'[Date]<=MAX('Test Charges Date Table'[Date])
)
Cummulative Count prevMonth =
Calculate(
[Cummulative Count]
,PARALLELPERIOD('Test Charges Date Table'[Date],-1,MONTH)
)

Power BI IF Statement with two parameters from data in two columns from one table?

I am trying to have a user in Power BI select a date. Then I want my visual to sum all insurance policies' premium with an effective date ON or BEFORE that selected date AND an expiration date AFTER that selected date. This will show all policies currently in force. How can I do this?
In my head it sounds like an IF statement sorta like:
IF Policy[EffectiveDate] <= Calendar[Date] AND Policy[ExpirationDate] > Calendar[Date] Return [Current Year Premium]
I have no idea how to write this so it works though.
Try using a measure like this
Measure =
VAR _selectedDate =
MAX ( 'Calendar'[Date] )
RETURN
CALCULATE (
SUM ( Policy[Premium] ),
FILTER (
Policy,
Policy[EffectiveDate] <= _selectedDate
&& Policy[ExpirationDate] > _selectedDate
)
)

Calculating Monthly Average over time with only Start and End Dates in Power BI

In order to track our average headcounts and turnover trends, I had created a report in Power BI that essentially expanded a table with employee start/end information to give a record for each associate every day they were employed at the company.
While this solution works, I end up with a table containing millions of rows which does not seem very efficient.
I have looked into other possible solutions in DAX, but have not found anything that will give me the exact same output. It seems like most solutions rely on taking the timing from the start date and end date of a month and then averaging them, which is not quite what I am trying to do.
I have attached a simplified pbix file that shows the desired output of what I am trying to get at. Any advice would be appreciated.
pbix example
Final code ended up looking like this:
All Employees = countrows ('Employees')
Terminations =
Calculate(
Countrows('Employees'),
USERELATIONSHIP('Employees'[End Date],'Calendar'[Date])
)
Active Employees =
AVERAGEX(
VALUES('Calendar'[Date]),
VAR CurrentDate = 'Calendar'[Date]
VAR HiredBeforeCurrentDate =
Filter(
ALL('Employees'[Start Date]),
'Employees'[Start Date] <= CurrentDate
)
VAR HiredAfterCurrentDate =
FILTER(
ALL('Employees'[End Date]),
OR('Employees'[End Date] >= CurrentDate, isblank('Employees'[End Date])
)
)
RETURN
CALCULATE(
Countrows('Employees'),
HiredBeforeCurrentDate,
HiredAfterCurrentDate,
ALL('Calendar')
))

DAX - Calculating at the Line Level (SUMX) with Multiple Filters

What I'm trying to get DAX to do is:
Look across each row in a table of HR data.
Identify the start date of the employee ("employee a")
Sum up the number of other employees in the table with the following filters applied:
a. Successfully completed their assignment
b. Ended their assignment BEFORE the start date + 31
c. Ended their assignment AFTER the start date - 31 (which is to say within a month of employee a's start date)
d. Started before employee a (to not count employee a or anyone in their cohort in the count)
e. Has the same job title as employee a.
This is essentially asking the question in normal English "for each of my employees, how many other employees with the same job title ended their assignments successfully within a month of that employee starting?" and in DAX is basically just "how do I apply multiple filter criteria to a SUMX or COUNTAX measure/calculated column?"
The measure I've already tried is:
Contractors Available = COUNTAX(
'BAT VwRptMspAssignment',
CALCULATE(
DISTINCTCOUNT('BAT VwRptMspAssignment'[assignmentgk]),
FILTER(
FILTER(
FILTER(
FILTER(
FILTER(ALL('BAT VwRptMspAssignment'),
'BAT VwRptMspAssignment'[End.Date]<EARLIER('BAT VwRptMspAssignment'[Start.Date])+31),
'BAT VwRptMspAssignment'[End.Date]>EARLIER('BAT VwRptMspAssignment'[Start.Date])-31),
'BAT VwRptMspAssignment'[Start.Date]<EARLIER('BAT VwRptMspAssignment'[Start.Date])),
'BAT VwRptMspAssignment'[EoaReason]="Successful Completion"),
'BAT VwRptMspAssignment'[JobPostingTitle.1]=EARLIER('BAT VwRptMspAssignment'[JobPostingTitle.1]))
)
)
And the calculated column I tried was:
Contractors Available.1 = SUMX(
FILTER(
FILTER(
FILTER(
FILTER(
FILTER(
FILTER(ALL('BAT VwRptMspAssignment'),
'BAT VwRptMspAssignment'[customergk]=EARLIER('BAT VwRptMspAssignment'[customergk])),
'BAT VwRptMspAssignment'[JobPostingTitle.1]=EARLIER('BAT VwRptMspAssignment'[JobPostingTitle.1])),
'BAT VwRptMspAssignment'[End.Date]<EARLIER('BAT VwRptMspAssignment'[Start.Date])+31),
'BAT VwRptMspAssignment'[End.Date]>EARLIER('BAT VwRptMspAssignment'[Start.Date])-31),
'BAT VwRptMspAssignment'[Start.Date]<EARLIER('BAT VwRptMspAssignment'[Start.Date])),
'BAT VwRptMspAssignment'[EoaReason]="Successful Completion"),
'BAT VwRptMspAssignment'[FinishFlag])
but neither of these solutions have worked.
Does anyone have any idea why or what else I can try to accomplish this? An example of the data format, exported to Excel:
"Contractors Available.2" is the calculated column.
Note the 521 in the first line. If I apply all of these filters in Excel, it should be zero, this job title is unique in the dataset. It says 107 "Technical Writer - Expert" rows should have ended within a month of 9/26/2017, but these are the only 3 technical writers in the dataset, and zero of the other two ended their assignments within a month of 9/30/2016:
Try something like this for a calculated column:
Contractors Available.1 =
VAR StartDate = 'BAT VwRptMspAssignment'[Start.Date]
VAR JobTitle = 'BAT VwRptMspAssignment'[JobPostingTitle.1]
RETURN
COUNTROWS (
FILTER (
'BAT VwRptMspAssignment',
'BAT VwRptMspAssignment'[End.Date] < StartDate + 31
&& 'BAT VwRptMspAssignment'[End.Date] > StartDate - 31
&& 'BAT VwRptMspAssignment'[Start.Date] < StartDate
&& 'BAT VwRptMspAssignment'[EoaReason] = "Successful Completion"
&& 'BAT VwRptMspAssignment'[JobPostingTitle.1] = JobTitle
)
)
The EARLIER functions are not necessary because the variables will keep the context where they were defined, which is the rowcontext.
EDIT:
I tested my formula with the data you provided and it seems to work. I changed the [End.Date] in the second row, to get a result in the first row.