I already posted this question in die power bi community some time ago and revisited my question today. Since I still cannot wrap my head around it I thought I'd ask it here again.
Original: https://community.powerbi.com/t5/Desktop/Calculate-ignores-outer-Filter-context/m-p/1933884#M737076
here is the quesion (again):
After searching "running total" and "filter context" I couldn't find something that matches my question (in a reasonable time).
My base Idea was to compute a running total in DAX. I have a fact table
facts
and a calendar table (marked as such)
calender-table
The "is_this_year" flag marks the current year (2021) with 1, otherwise 0. So the dates start in early 2019.
The setup is as follows: I have a page-level filter on "is_this_year":
page-level-filter
and I wrote the following Measure:
theMeasure =
VAR cur_max = MAX ( 'Calendar'[Date] )
RETURN
CALCULATE ( MIN ( 'Calendar'[Date] ), 'Calendar'[Date] <= cur_max )
Because of the Page-level filter I assument that I would get 1.1.2021 for every row but instead I get this:
result
This lookes like the page-level filter is ignored.
My reasoning here is that in the DAX generated in Power BI I get a filter on Calendar[is_this_year] which is essentially a table
is_this_year
1
In the measure itself I modify the filter context and add a filter on the [Date] Column of the calendar table. My understanding of filter contexts was that, because those filters are applied on different columns they should exist side by side, meaning we have the following filters in the final filter context:
[is_this_year] = 1
[Date] <= 5.5.2021 (for example)
So I would expect to get a row like this:
Date
The measure
05.05.2021
01.01.2021
But I we can see in the picture above I get 03.01.2019 as a measure value.
Can someone help me understand this?
I do see that the Solution posted in the original question works, yet I do not see why I need to pass the filter again.
The solution was:
theMeasure =
VAR cur_max = MAX ( 'Calendar'[Date] )
RETURN
CALCULATE ( MIN ( 'Calendar'[Date] ), 'Calendar'[Date] <= cur_max, VALUES('Calendar'[is_this_year]) )
example file here:
https://1drv.ms/u/s!AtFejN9ixXnChShZpu7MiEgoXVw5?e=ZCdERm
Thank You! I hope someone can shed some light here :)
Related
This should be simple, but I find it incredibly frustrating. I have a table with information on Cases, with Date Initiated, Date to Pricing, and Partner columns. I want to count the cases by Partner that were initiated within a date range, and have a Date To Pricing entry. Here's my code:
Rank Pard Cases Priced. =
VAR Table0 =
FILTER ( 'Cases',
not ISBLANK( [Date To Pricing] )
&& [Date Initiated] >= date(2021,1,1)
&& [Date Initiated] <= DATE(2021,12,31) )
VAR
Table1 =
SUMMARIZECOLUMNS(
'Cases'[Partner],
"Price_Pard",
countrows(FILTER ( 'Cases',
not ISBLANK( [Date To Pricing] )
&& [Date Initiated] >= date(2021,1,1)
&& [Date Initiated] <= DATE(2021,12,31) ) ) )
VAR
Table2 =
ADDCOLUMNS( Table1, "Rank", RANKX(Table1, [Price_Pard],, DESC, Skip))
RETURN
MINX(Table2, [Rank])
When I EVALUATE this code in DAX Studio, ending with RETURN Table2, I get exactly what I'm looking for, a table of the Partners, the counts, and the ranks.
I'm using this measure on a visual table that has the Partner name, so I expect it to give me a column with the expected ranks. However, I get the dreaded message:
I really have no idea what that means. Where does the "AddMissingItems" come from? I've been getting it a lot lately, even with measures that are simpler than this one, and don't involve any summarizing. I think the problem might be with having a FILTER inside SUMMARIZECOLUMNS apparently that's not well-supported. I've been researching this for 2 hours, and haven't found a solution, or an alternative that works. Most of what I read is confusing rather than helpful.
If I use the measure all by itself in a Card, with no Partner filter context, it works and gives me a value of 1, as expected (the min rank).
So my questions are:
(1) What does that error message mean?
(2) How can I get my code to work?
(3) If I need to restructure the query using SELECTCOLUMNS and grouping, please give me specifics. I've tried a few variations on that, but without any luck. In DAX Studio, the results are the same for every Partner: the total number of lines, and rank 1.
I have been trying for a few days to do this with no avail and its probably something simple.
I am trying to calculate the PRED_BL column which is based on PRED_WORKLOAD + PRED_REC - WORKDONE
As you can see I can do the first day because I have the PRED_WORKLOAD volume for the 04/10/2021, but PRED_WORKLOAD future dates are blank - what I need to do is bring the 314419 from the 4ths PRED_BL column as the PRED_WORKLOAD value for the 5th October, to start the calculation but also make sure the calculated PRED_BL's are used as the starting points for each of the future dates.
This is probably something simple but for a Power BI newbie like me not so.
Hope someone can help me, thanks in advance
As in this similar post, you can't recursively define columns based on previous ones but you can compute cumulative totals instead to a similar effect.
It would look something like this:
PRED_BL =
SUMX (
FILTER ( Table1[DATE], Table1[DATE] <= MAX ( Table1[DATE] ) ),
Table1[PRED_WORKLOAD] + Table1[PRED_REC] - Table1[WORKDONE]
)
I am trying to give rank to each row in daily stock price details table to figure out previous day closing price:
The code I use is:
rank =
RANKX(
FILTER(
ALL(NSE_DAILY_REPORT),
NSE_DAILY_REPORT[SYMBOL]="ADLABS"
),
MAX(NSE_DAILY_REPORT[TDATE]),,
ASC
)
The problem is that it returns a rank of 1 for all rows.
Try changing MAX(NSE_DAILY_REPORT[TDATE]) to NSE_DAILY_REPORT[SCLOSE]
The second argument expects an expression to compare to evaluations of that same expression in the filtered subset. Using MAX will yield that every record gets ranked in a set of just one record, hence the 1 for all rows.
So if I understand correctly your goal is to get the closing price of the day before?
In that case RANKX() is not necessary in contrast to the post you shared as an example. There they create ordinality by creating a ranking first and then perform a pretty inefficient calculation to get the previous in rank. There already is ordinality as you have a date column. Power BI already knows how to interpret that scale, so getting a value for a previous day does not need an additional ranking.
There's tons of posts around stack overflow dealing with this problem. Have a look around to learn more. For your particular problem, the solution will be a calculated column with code looking something like:
PreviousDay =
CALCULATE (
SUM ( NSE_DAILY_REPORT[SCLOSE] ),
FILTER (
ALLEXCEPT ( NSE_DAILY_REPORT, NSE_DAILY_REPORT[SYMBOL] ),
NSE_DAILY_REPORT[TDATE] = EARLIER(NSE_DAILY_REPORT[TDATE]) - 1
)
)
It will do the trick, but it still has some inefficiencies you can improve by looking through other examples like this
I have following scenario which has been simplified a little:
Costs fact table:
date, project_key, costs €
Project dimension:
project_key, name, starting date, ending date
Date dimension:
date, years, months, weeks, etc
I would need to create a measure which would tell project duration of days using starting and ending dates from project dimension. The first challenge is that there isn't transactions for all days in the fact table. Project starting date might be 1st of January but first cost transaction is on fact table like 15th on January. So we still need to calculate the days between starting and ending date if on filter context.
So the second challenge is the filter context. User might want to view only February. So it project starting date is 1.6.2016 and ending date is 1.11.2016 and user wants to view only September it should display only 30 days.
The third challenge is to view days for multiple projects. So if user selects only single day it should view count for all of the projects in progress.
I'm thankful for any help which could lead towards the solution. So don't hesitate to ask more details if needed.
edit: Here is a picture to explain this better:
Update 7.2.2017
Still trying to create a single measure for this solution. Measure which user could use with only dates, projects or as it is. Separate calculated column for ongoing project counts per day would be easy solution but it would only filter by date table.
Update 9.2.2017
Thank you all for your efforts. As an end result I'm confident that calculations not based on fact table are quite tricky. For this specific case I ended up doing new table with CROSS JOIN on dates and project ids to fulfill all requirements. One option also was to add starting and ending dates as own lines to fact table with zero costs. The real solution also have more dimensions we need to take into consideration.
To get the expected result you have to create a calculated column and a measure, the calculated column lets count the number of projects in dates where projects were executed and the measure to count the number of days elapsed from [starting_date] and [ending_date] in each project taking in account filters.
The calculated column have to be created in the dim_date table using this expression:
Count of Projects =
SUMX (
FILTER (
project_dim,
[starting_date] <= EARLIER ( date_dim[date] )
&& [ending_date] >= EARLIER ( date_dim[date] )
),
1
)
The measure should be created in the project_dim table using this expression:
Duration (Days) =
DATEDIFF (
MAX ( MIN ( [starting_date] ), MIN ( date_dim[date] ) ),
MIN ( MAX ( [ending_date] ), MAX ( date_dim[date] ) ),
DAY
)
+ 1
The result you will get is something like this:
And this if you filter the week using an slicer or a filter on dim_date table
Update
Support for SSAS 2014 - DATEDIFF() is available in SSAS 2016.
First of all, it is important you realize you are measuring two different things but you want only one measure visible to your users. In the first Expected result you want to get the number of projects running in each date while in the Expected results 2 and 3 (in the OP) you want the days elapsed in each project taking in account filters on date_dim.
You can create a measure to wrap both measures in one and use HASONEFILTER to determine the context where each measure should run. Before continue with the wrapping measure check the below measure that replaces the measure posted above using DATEDIFF function which doesn't work in your environment.
After creating the previous calculated column that is required to determine the number of projects in each date, create a measure called Duration Measure, this measure won't be used by your users but lets us calculate the final measure.
Duration Measure = SUMX(FILTER (
date_dim,
date_dim[date] >= MIN ( project_dim[starting_date] )
&& date_dim[date] <= MAX ( project_dim[ending_date] )
),1
)
Now the final measure which your users should interact can be written like this:
Duration (Days) =
IF (
HASONEFILTER ( date_dim[date] ),
SUM ( date_dim[Count of Projects] ),
[Duration Measure]
)
This measure will determine the context and will return the right measure for the given context. So you can add the same measure for both tables and it will return the desired result.
Despite this solution is demonstrated in Power BI it works in Power Pivot too.
First I would create 2 relationships:
project_dim[project_key] => costs_fact[project_key]
date_dim[date] => costs_fact[date]
The Costs measure would be just: SUM ( costs_fact[costs] )
The Duration (days) measure needs a CALCULATE to change the filter context on the Date dimension. This is effectively calculating a relationship between project_dim and date_dim on the fly, based on the selected rows from both tables.
Duration (days) =
CALCULATE (
COUNTROWS ( date_dim ),
FILTER (
date_dim,
date_dim[date] >= MIN ( project_dim[starting_date] )
&& date_dim[date] <= MAX ( project_dim[ending_date] )
)
)
I suggest you to separate the measure Duration (days) into different calculated column/measure as they don't actually have the same meaning under different contexts.
First of all, create a one-to-many relationship between dates/costs and projects/costs. (Note the single cross filter direction or the filter context will be wrongly applied during calculation)
For the Expected result 1, I've created a calculated column in the date dimension called Project (days). It counts how many projects are in progress for a given day.
Project (days) =
COUNTROWS(
FILTER(
projects,
dates[date] >= projects[starting_date] &&
dates[date] <= projects[ending_date]
)
)
P.S. If you want to have aggregated results on weekly/monthly basis, you can further create a measure and aggregate Project (days).
For Expected result 2 and 3, the measure Duration (days) is as follows:
Duration (days) =
COUNTROWS(
FILTER(
dates,
dates[date] >= FIRSTDATE(projects[starting_date]) &&
dates[date] <= FIRSTDATE(projects[ending_date])
)
)
The result will be as expected:
I've been struggling with DAX while creating a model to publish on Power BI and the actual problem is presented on the image here. Basically I need a column that shows the value from the predecessor time for the same id.
I did with ranking but wanted to know if it is possible to make it better.
How would you guys do it?
Rank = COUNTROWS(FILTER(test; [id] = EARLIER([id]) && [Date] <= EARLIER([Date])))
Past = if(test[Rank]=1;0; LOOKUPVALUE(test[qt];teste[Rank];test[Rank]-1;test[id];test[id]))
This is a solution tested with the basic model you posted, I don't guarantee this is a machine low cost expression but you can give it a try.
I've created a column called PREVIOUS in which is calculated the previous qty for every row based on the date for the same id.
PREVIOUS =
CALCULATE (
MAX ( TableName[qt] ),
FILTER (
TableName,
EARLIER ( TableName[id] ) = TableName[id]
&& EARLIER ( TableName[date] ) > TableName[date]
)
)
The following is a Power BI table using the PREVIOUS column.
Let me know if this helps.