How to make a Power BI DAX measure apply to rows individually? - powerbi

I have a table of Projects and a table of Weeks (representing the number of weeks from today)
Trying to use this measure to spread the value of each project over the project's duration:
RevenuebyWeek=
IF(
MAX('Table'[InForecast]) = 1 &&
SUMX('Table','Table'[Start])<=TODAY()+(max(Weeks[WeekRef])*7) &&
TODAY()+(MAX(Weeks[WeekRef])*7)<sumx('Table','Table'[Finish]),
sumx('Table','Table'[RevenueBacklog])/sumx('Table','Table'[Weeks]),0
)
This works at the project level, but not once you try to aggregate these values, see screenshot below.
Is this because the measure is applying to all projects collectively? How do I make it apply to projects individually?

Yes, you apply the measure to all projects.
SUMX('Table','Table'[Start])<=TODAY()+(max(Weeks[WeekRef])*7)
SUMX('Table','Table'[Start]) -- seems it can be the unbeatable Value when aggregating
Create 2 measures - one for "Hasonevalue" and other for your aggrigation and use a "Switch" or IF

SUMX does work by row, I just needed to re-word the IF statement into a FILTER within the SUMX. Like this:
RevenueByWeek=
SUMX(
FILTER(
'Table',
'Table'[InForecast] = 1 &&
'Table'[Start] <=TODAY()+(SELECTEDVALUE(Weeks[WeekRef])*7) &&
TODAY()+(SELECTEDVALUE(Weeks[WeekRef])*7)<'Table'[Finish]
),
'Table'[RevenueBacklog] / 'Table'[Weeks]
)

Related

Calculate ignores outer Filter context

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 :)

Power BI: Use dim table in conditional formatting as criteria, keeping one measure instead of multiple

I have the following structure of tables:
fact_Phone (* < 1) Dim_Users (* <> 1) Dim_user_ID
The fact_Phone table have usernames. This is many to one, single direction to dim_users
The dim_users have the username and proper name but not the ID. This is many to one in both directions to dim_user ID
The dim_user_ID have proper name, user ID and country.
I figured out how to check if the handling times of the calls are on target or not, although I had to separate the handling times into two different measures first, leading to the need of two columns. This is not wanted, and I cannot figure out how to merge them into one measure, while still checking for my country condition from my dim_user_ID table.. any ideas?
In my Matrix, I use dim_user_ID[country] as my rows with the dim_user_ID[name] as the secondary row, and then I tried to use my calculated measures to show the average handling times. So far, so good. ..except that they are in different columns.
This is what I have tried so far, although that means I have to have two measures, ultimately forcing me to have two columns (one for each country, which is not wanted):
AHT (Phone NO) = DIVIDE(
SUMX(
FILTER(
fact_Phone,
RELATED(dim_user_ID[country])="NO"
), fact_Phone[Total AHT]
),
SUMX(
FILTER(
fact_Phone,
RELATED(dim_user_ID[country])="NO"
), fact_Phone[Total calls answered]
)
)
AHT (Phone SE) = DIVIDE(
SUMX(
FILTER(
fact_Phone,
RELATED(dim_user_ID[country])="SE"
), fact_Phone[Total AHT]
),
SUMX(
FILTER(
fact_Phone,
RELATED(dim_user_ID[country])="SE"
), fact_Phone[Total calls answered]
)
)
Then based on this one, I create one new measure that can be used for the conditional formatting:
Check AHT on target =
IF(
'1 Measures'[AHT (Phone NO)] > 240
|| '1 Measures'[AHT (Phone SE)] > 260,
0,
1
)
Solved:
Kept the two measures above, and changed the last measure to this:
Check AHT on target =
IF(
NOT(ISBLANK('1 Measures'[AHT (Phone NO)]))
|| NOT(ISBLANK('1 Measures'[AHT (Phone SE)])),
IF(
'1 Measures'[AHT (Phone NO)] > 240
|| '1 Measures'[AHT (Phone SE)] > 260,
0,
1
))
Then it worked to us this measure as the "What field should we base this on?" in the conditional formatting for a simpler AHT measure:
AHT (Phone) = DIVIDE(SUM(fact_Phone[Total AHT]),SUM(fact_Phone[Total calls answered]))
Solved it. I only had to create the to measures AHT (Phone NO) and AHT (Phone SE), then I could use the "Check AHT on target" measure on one simpler measure being ´AHT (Phone) = DIVIDE(SUM(fact_Phone[Total AHT]),SUM(fact_Phone[Total calls answered])) ..now I just need to figure out how to return nothing if the AHT for the specific measures result in blanks.. and I will mark this as the answer later, I have to wait two days though.

PowerBI how to use one slicer with two columns (dates)

I have a table with columns 'date from' and 'date to', and visualize them as bars using asTimeline visual.
I want to add a slicer which will work on both of these fields simultaneously. Currently I have two slicers working independently on each of those fields:
This is not really intuitive. Since start and end both define a period in time, if the period is inside the slider selection, it should be included. But slicers work on only one field. So I probably need to perform some DAX magic to create a field based on those two, but I don't know where to begin.
First create an measure to check a row overlaps the your date range:
Date Included =
IF (
FIRSTNONBLANK ( DateTable[Start Date], 1 ) <= MAX ( 'Calendar'[Date] ) &&
FIRSTNONBLANK( DateTable[End Date], 1 ) >= MIN ( 'Calendar'[Date] ),
"Include",
"Exclude"
)
and , add above Measure as a filter on your visualisation, where Date Included is Include
Than you can filter your Calendar table to single value, or range.
Also,only overlapping rows from your fact table will be displayed.
The problem can be solved by using a separate calendar-table and a measure: PowerBI filter- selected Date between Start and End date
Another way to solve this, and keep using the two slicers more intuitively, is described here: https://radacad.com/from-and-to-date-slicers-in-power-bi-filtering-based-on-two-fields. The solution describes how to set the properties of those timeline-slicers so that it makes a bit more sense for the user (set the "Start of employment" slicer as Type - After and the "End of employment" as Type - Before).

Power BI - Running total column with many filters

I have table "Sales" (fields: Product, Country, Date, Sales) with monthly sales across many products and countries. Also I have tables with calendar, list of products, list of counties that are linked with this table. I want to add column to "Sales" with running total sales across each Product/Country, see the field with desired result "Running total".
I tried to use
YTD = TOTALYTD(SUM(Sales[Sales]); Calendar[Date]) but it didn't work. I think I need to use filters in TOTALYTD function, but I also didn't manage to understand how. Can you suggest to me a right solution to my case?
Table "Sales"
I was suggested to use this code
Column =
SUMX (
FILTER (
Sales,
Sales[Product] = EARLIER ( Sales[Product] )
&& Sales[Country] = EARLIER ( Sales[Country] )
&& Sales[Date] <= EARLIER ( Sales[Date] )
&& YEAR ( Sales[Date] ) = YEAR ( EARLIER ( Sales[Date] ) )
),
Sales[Sales]
)
It worked.
I partially coped with my issue by creating set of measures for each combination of product and country:
A_US = TOTALYTD(SUM(Sales[Sales]);'Calendar'[Date];FILTER(All(Sales);Sales[Product]="A"&&Sales[Country]="US"))
A_Canada = TOTALYTD(SUM(Sales[Sales]);'Calendar'[Date];FILTER(All(Sales);Sales[Product]="A"&&Sales[Country]="Canada"))
and so on. But what if i have 100 products and 30 countries? I think I need to create a column "Running total" in "Sales" that calculates running total for each product and aech country.
The problem of the TOTALYTD function is that it takes only one filter.
The tricks is to use the filter function like you do on the second response.
To use only one column for all product and country you have to get the context of the current row .
To achieve this you have the function earlier in dax.
Here the documentation about earlier : https://learn.microsoft.com/en-us/dax/earlier-function-dax
The column need to be build with this expression :
TOTALYTD(SUM(Sales[Sales]),'Calendar'[Date],filter(Sales,and(Sales[Country]=EARLIER(sales[Country]),sales[Product] = EARLIER(sales[Product]))))

DAX measure: project duration (days) from dimension starting & ending date

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: