Calculate monthly value between 2 tables without an explicit relationship in Power BI model - powerbi

I am trying to create a measure that calculates (a/qty)*100 for each month,
where qty commes from Delivery table (generated with an R script)
month qty
<date> <dbl>
1 2019-02-01 1
2 2019-03-01 162
3 2019-04-01 2142
4 2019-05-01 719
And a comes from a table TABLE_A that has been created within Power BI that looks like this :
Client Date a
x 2019-03-07 3
x 2019-04-14 7
y 2019-03-12 2
So far, I managed to calculate that value overall with the following measure formula :
MEASURE = CALCULATE( (Sum(TABLE_A[a])/sum(Delivery[qty]))*100)
The issue I have is that I would need this measure monthly (i.e. join the tables on month) without explicitly defining a link between the tables in the PowerBI model.

For each row in TABLE_A you need to look up the corresponding qty in Delivery, so try something along these lines:
MEASURE =
DIVIDE(
SUM( TABLE_A[a] ),
SUMX(
TABLE_A,
LOOKUPVALUE(
Delivery[qty],
Delivery[month], EOMONTH( TABLE_A[Date], -1 ) + 1
)
)
) * 100
The formula EOMONTH( TABLE_A[Date], -1 ) returns the end of the previous month relative to that date and adding 1 day to that to get the start of the current month for that date.

Related

What is the purpose of using VALUES or ALL in the first parameter of an iterator function?

I know that only CALCULATE can modify the filter context. However following are 2 example using VALUES and ALL.
Example 1:
Revenue =
SUMX(
Sales,
Sales[Order Quantity] * Sales[Unit Price]
)
Revenue Avg Order =
AVERAGEX(
VALUES('Sales Order'[Sales Order]),
[Revenue]
)
What is the purpose of VALUES in AVERAGEX function? Is this to add an additional filter context?
Example 2:
Product Quantity Rank =
RANKX(
ALL('Product'[Product]),
[Quantity]
)
What is the purpose of using ALL in an iterator function?
Suppose we have a table like this:
ID
Sales Order
Order Quantity
UnitID
Unit Price
1
101
10
4
39.99
2
101
15
3
24.99
3
102
5
2
15.99
4
103
5
1
14.99
5
103
10
3
24.99
Since the Sales Order column has duplicates,
Revenue Avg Order = AVERAGEX ( VALUES ( Sales[Sales Order] ), [Revenue] )
gives a different result than
Revenue Avg ID = AVERAGEX ( Sales, [Revenue] )
since the first averages over the three Sales Order values whereas the second averages over the five ID rows.
Using DISTINCT instead of VALUES would work too.
Using ALL is instead of VALUES gives the same total but ignores the local filter context from the table visual:
Revenue Avg All = AVERAGEX ( ALL ( Sales[Sales Order] ), [Revenue] )
In this context, ALL is acting as a table function that returns all of the distinct values of the column specified ignoring filter context.

Rolling 6 month Open Contracts in Power BI

I need to show how many active contracts we have open for each month in the last 6 months. I am trying to figure out a way to display this. Here is my table
Machine Enrollment# StartDate EndDate
A 1 1/2/2016 6/18/2019
B 2 12/15/2012 5/12/2034
C 3 3/25/2019 4/25/2021
D 4 1/7/2000 7/15/2019
A 5 10/1/2019 10/1/2025
I have thousands of rows. I want to be able to show a rolling 6 month visual for how many machines are under contract. So in this small example it would look like this
Apr-19 June-19 Jul-19 Aug-19 Sep-19 Oct-19
4 4 3 2 2 3
Where do I even begin in creating this? In the past, we have just looked at the numbers for the current month and tacked those results onto the end of a static table and deleted the column from over 6 months ago. I have been assigned to automate this report in Power BI. I am guessing I need to create a column/measure that looks at the EndDate and compares it to the filtered Date in the visual (ie: Aug-19) and determines if the contract was open at that time. But I do not know. Any help is much appreciated. Thanks in advance!
I think I found a solution for what you are looking for. You may find a sample pbix file here.
1. Create a calendar table
A calendar table is required to filter/slice the time periods. The calendar table needs to have a unique Date column, and optional columns such as Year, Quarter, and Month, depending on what units of period you need in the analysis.
A calendar table can be most easily created as a DAX calculated table. Here is an example of a minimal calendar table required in this use case.
Calendar =
ADDCOLUMNS(
CALENDAR( MIN( Contracts[StartDate] ), MAX( Contracts[EndDate] ) ),
"Year Month", FORMAT( [Date], "mmm-yy" ),
"Year Month Number", YEAR( [Date] ) * 100 + MONTH( [Date] )
)
2. Create a measure to calculate number of open contracts
Every numbers calculated and shown in reports need to be defined as measures.
Let's think about the number of May-19. The current filter context includes all 31 dates in the Calendar table between 2019-05-01 and 2019-05-31. In this case, how can we think of an open contract? If the contract starts after 2019-05-31, it is not open. If the contract ends before 2019-05-01, it is not open as well. Therefore the open contract meets this condition.
Starts on or before 2019-05-31 and
Ends on or after 2019-05-01
Below is the measure definition to count the number of contracts based on this condition.
# Open Contracts =
VAR MinDate = MIN( 'Calendar'[Date] )
VAR MaxDate = MAX( 'Calendar'[Date] )
RETURN COUNTROWS(
FILTER(
Contracts,
Contracts[StartDate] <= MaxDate
&& Contracts[EndDate] >= MinDate
)
)
3. Add dynamic filter for last 6 months
If I was understanding correctly, the requirement is to show monthly number of last 6 calendar months, excluding this month. I could not find a straightforward way for this. My solution may contain a bit of hacky scent.
Power BI does not have built-in filter support based on calendar months relative to now. We need to build a custom logic to achieve this. I did it by creating a measure that indicates whether current filter context is within the desired period. This measure is a flag that returns 1 if the filter context is a single calendar month which is included in the last 6 calendar months, or returns BLANK otherwise.
__Last6MonthFlag =
VAR YearMonths = CALCULATETABLE(
VALUES( 'Calendar'[Year Month] ),
REMOVEFILTERS( 'Calendar'[Year Month] ),
'Calendar'[Date] > EOMONTH( TODAY(), -7 )
&& 'Calendar'[Date] <= EOMONTH( TODAY(), -1 )
)
RETURN IF(
HASONEVALUE( 'Calendar'[Year Month] )
&& SELECTEDVALUE( 'Calendar'[Year Month] ) IN YearMonths,
1
)
Then I used this measure in the visual filter like this.
You need to do below activities to achieve your requirement.
Define a calendar table holding all the dates for your report. Define a calculated column for Month-Year. Month-Year = FORMAT('CalendarTable'[Date], "MM-YYYY")
You can define a calculated measure, which will return 1 if the end date of the contract is < 6 months from current date (you can use TODAY() function). This function will help in rolling calculation based on current date. Otherwise, this calculated measure will return NULL and SUM them.
You can drag the month-Year calculated column, defined in step no. 1, to the column axis. You can drag the calculated measure, defined in step no.2, to the values section. PowerBI control by default filters out the NULL values. So, when you use the calculated measure defined in step no. 2, you will get values only for the last 6 months. As the calculation is defined based on TODAY(), it will be a running calculation.

Power BI - Cumulative SUM filtered by current row values

I have a table with three columns - list_id, id, daily_return. id is basically a number sequence increment, reset for every list_id.
Example:
list_id id daily_return
1 1 0.2
1 2 0.18
1 3 0.35
2 1 0.15
2 2 0.18
2 3 0.23
I need to create a calculated measure on the chart I am creating such that it creates a running total of daily_return for the same list_id, ordered by the id column.
I am creating a measure in the chart, since I want the rows to be filtered by the user and the calculation itself will be more complex.
How do I get the current list_id and id, so I may use it in my formula?
This is what I have so far. I tried using EARLIER/EARLIEST without success.
cumulative_return = CALCULATE(SUM('CMC Daily Return'[daily_return]), 'CMC Daily Return'[list_id]=EARLIER([list_id]), 'CMC Daily Return'[id]<=EARLIER([id]))
I came up with the following formula that works, but if there is a better one, then I am all ears.
cumulative_return = CALCULATE(SUM('CMC Daily Return'[daily_return]), FILTER( ALLSELECTED('CMC Daily Return'), 'CMC Daily Return'[list_id] = max('CMC Daily Return'[list_id]) ), FILTER( ALLSELECTED('CMC Daily Return'), 'CMC Daily Return'[id] <= max('CMC Daily Return'[id]) ) )

DAX measure to count IDs satisfying a threshold condition

SalePersonId Month Qty
1 Jan-18 5
2 Jan-18 7
1 Feb-18 1
2 Feb-18 8
3 Feb-18 12
I need to create a measure which gives me a count of salespersons whose total sales quantity is more than 10 for the year 2018.
The result should be 2 (Sale person 1 & 3)
I can achieve this in T-SQL with the following query:
SELECT COUNT(Distinct EmpId) FROM T1 GROUP BY UserId HAVING SUM(Qty) > 10
How can I do the same in DAX?
Here's one possible approach:
= COUNTROWS(
FILTER(
SUMMARIZECOLUMNS(
T1[SalePersonId],
"Total", SUM(T1[Qty])),
[Total] > 10))
The SUMMARIZECOLUMNS part is essentially
SELECT SalePersonId, SUM(Qty) AS 'Total' FROM T1 GROUP BY SalePersonId
The FILTER part is equivalent to the HAVING clause and then you just count the rows in the resulting table.

Power BI Rolling Total Previous Month DAX

I am working in POWER BI and trying to calculate a DAX expression for the rolling total of the previous month. I have a filter where I select a certain month, I would like to calculate the rolling total for the previous month.
Below is the calculation that works perfectly to calculate the rolling total for the selected date range.
How can I calculate the previous months rolling total?
Rolling_Total_Current_Month = CALCULATE(
SUM(SalesInvoice[Sales])
,FILTER(ALLSELECTED(SalesInvoice), (SalesInvoice[Date]) <= MAX(SalesInvoice[Date])))
Here is a sample of my data, I have sales per day, for multiple categories, (in fact i have a couple more columns of details but this is simplified)
Date Day Amount Category
1/1/2016 1 100 A
1/1/2016 1 120 B
1/1/2016 1 90 C
1/2/2016 2 500 A
1/2/2016 2 321 B
1/2/2016 2 143 C
So far I have come up with an equation to solve the rolling total, but when I try to slice is and view the rolling total of a single category it does not work for the previous month. I just keeps the original rolling total for the previous month.
Here is the equation for the rolling total previous month that works. But does not recalculate a rolling total for the previous month once sliced based on category.
PREVIOUS_MONTH_ROLLING_TOTAL =
CALCULATE(
[Current Sales]
,FILTER(
ALL( Orders )
,Orders[MonthNumber] = MAX( Orders[MonthNumber] ) - 1
&& Orders[Day] <= MAX( Orders[Day] )
)
)
I have solved how to get the previous months rolling total.
You must do three things. First create a Month Number column in your data sheet (this is used as an integer to subtract 1 month from). You must also create a days column as well.
Then create a measure for Current Sales or whatever your value is.
Create a measure for the current month sales
Current Sales = SUM(Orders[Amount])
Then this equation.
PREVIOUS_MONTH_ROLLING_TOTAL =
CALCULATE(
[Current Sales]
,FILTER(
ALL( Orders )
,Orders[MonthNumber] = MAX( Orders[MonthNumber] ) - 1
&& Orders[Day] <= MAX( Orders[Day] )
)
)
The Idea of this equation is to be able to display the previous months rolling total on a chart with the X axis as "DAY" (so 1-31) Then you can view the current month, previous month, same period last year all on the same chart or table.
Try something along these lines:
Rolling_Total_Previous_Month =
VAR CurrentMonth = MAX(SalesInvoice[Date])
VAR PreviousMonth = EOMONTH(CurrentMonth,-1)
RETURN CALCULATE(SUM(SalesInvoice[Sales]), SalesInvoice[Date] <= PreviousMonth)
To start of, I have a data like this in a table called as Orders-
Date Amount
12/12/2017 100
12/12/2017 200
12/12/2017 300
1/1/2018 400
1/1/2018 500
I first create a calculated column called as Year & Month by using the formula:-
Year = YEAR(Orders[Date])
Month = FORMAT(Orders[Date],"mmmm")
Then I create a column called as Month Number which will be helpful for sorting when more than one year is involved in the table and as well as to Identify the Previous Months.
MonthNumber = DATEDIFF(Min(Orders[Date]),Orders[Date],MONTH)
Current Month Sales can be a measure or a Calculated column. Qn the Question, you had your answer for current month sales via a calculated column and if you want to go for a measure then something like this would work on a summary table.
Current Month Sales = SUm(Orders[Amount])
I would also create a column called as Key:-
Key = Orders[MonthNumber] & Orders[Category]
Now, for the Previous Month Sales, I would create a measure that looks for selected MonthNumber that we created.
Previous Month Sales =
Var SelectedCategory = SELECTEDVALUE(Orders[Category])
Var SelectedMonthNumberr = SELECTEDVALUE(Orders[MonthNumber]) - 1
Var ReqKey = SelectedMonthNumberr & SelectedCategory
Return
IF(ISBLANK(SelectedCategory) <> True(),
CALCULATE(SUM(Orders[Amount]),FILTER(ALL(Orders), Orders[Key] = ReqKey)),
CALCULATE(SUM(Orders[Amount]),FILTER(ALL(Orders), Orders[MonthNumber] = SelectedMonthNumberr)))
or to your Measure
PREVIOUS_MONTH_ROLLING_TOTAL =
CALCULATE(
[Current Sales]
,FILTER(
ALL( Orders )
,Orders[MonthNumber] = MAX( Orders[MonthNumber] ) - 1
&& Orders[Day] <= MAX( Orders[Day] )
)
)
You can just add another filtering item as && Orders[Category] = SELECTEDVALUE(Orders[Category]) but won't work when you don't have any categories selected or on a table or visual which doesn't have categories. So, you would need to define an if else logic here as I have quoted on my measure formula.
Do let me know, if this helps or not.