DAX Cumulative Total Comparison from Different Tables - powerpivot

How do I create a DAX measure that will show me the First Receipt Date where the Receipt Balance is greater than or equal to the Payment Balance?
For example, for Jun, I want the [Payment Receipt Date Avg] measure to show as Jan because the Receipt Balance is 10 which is greater than the Payment Balance of 8.
For Aug, it would show as Feb because that is the first date where the Receipt Balance is at least the Payment Balance of 13.
Desired Result:
Data Model
Table: Po Receipt
Table: Payment
Attempted Solution
I already have the below measures defined:
Receipt Balance:
=CALCULATE
(
SUM(PoReceipt[Quantity Received]),
FILTER
(
ALL ( PaymentDates ),
PaymentDates[Payment_FullDate] <= MAX ( PaymentDates[Payment_FullDate] )
)
)
Payment Balance:
=CALCULATE
(
SUM(Payment[Payment Amount]),
FILTER
(
ALL ( PaymentDates ),
PaymentDates[Payment_FullDate] <= MAX ( PaymentDates[Payment_FullDate] )
)
)

Create calculated columns to get the first date which has a net receipt running total (i.e. receipts less payments running total) greater than the payment amount in the current row context. The calculated columns will need to do the following:
Return the running total of [Payment Amount] for each [PO Num]. The EARLIER function is used so that for each row in the outer context, you sum all rows in the inner context where the inner row has a [Payment Date] less than or equal to the outer row, and the inner row's [Po Num] is equal to that of the outer row.
Return a summary table based on the PoReceipt table, which has an extended column "Receipt Balance Calc". The extended column calculates the running total of the PoReceipt[Quantity Received] similar to step 1. The summary table is grouped by the columns [Po Num] and [Receipt Date] to avoid performing the same calculation more than once (since there are multiple rows with the same [Po Num] due to the [Receipt Num] column).
Filter the result to only include rows where the Receipt Balance is greater than or equal to the Payment Balance.
See DAX code for calculated columns:
Payment[Payment Balance Calc]
=CALCULATE (
SUM ( Payment[Payment Amount] ),
FILTER (
Payment,
Payment[Payment Date] <= EARLIER ( Payment[Payment Date] )
&& Payment[Po Num] = EARLIER ( Payment[Po Num] )
)
)
Payment[Payment Receipt Date]
=CALCULATE (
MIN ( PoReceipt[Receipt Date] ),
ALL ( PaymentDates ),
FILTER (
ADDCOLUMNS (
SUMMARIZE (
PoReceipt,
PoReceipt[Po Num],
PoReceipt[Receipt Date]
),
"Receipt Balance Calc",
CALCULATE (
SUM ( PoReceipt[Quantity Received] ),
FILTER (
PoReceipt,
PoReceipt[Receipt Date] <= EARLIER ( PoReceipt[Receipt Date] )
&& PoReceipt[Po Num] = EARLIER ( PoReceipt[Po Num] )
)
)
),
[Receipt Balance Calc] >= EARLIER ( Payment[Payment Balance Calc] )
)
)
Finally, create the below measure to calculate the weighted average of the receipt dates:
Payment Receipt Date Avg:=
SUMX (
Payment,
Payment[Payment Amount] * Payment[Payment Receipt Date]
/ SUM ( Payment[Payment Amount] )
)

Related

DAX conditional measure errors out *Single Value for Column*

Sale Type is an attribute and is returning a Single Value error.
This expression works great in SQL but will not work here.
If ( [Sale Type] = "Upsell"
&& [Current Name] = "SaaS"
&& DATEDIFF ( [StartDate],[EndDate],Day ) + 1 > 364,
SUM ( [ARR] ),
SUM ( [TotalPrice] )
)

DAX Query on (Day Over Day)

I have the Sales table and a Date table
I wrote the below query to calculate the DOD Sales
Sales Volume := SUM([Sales])
Sales Volume (Prev) := CALCULATE([Sales Volume], PREVIOUSDAY('Date'[Date])
Sales Volume (DOD) = DIVIDE([Sales Volume]-[Sales Volume (Prev)],[Sales Volume (Prev)])
However, these query above will calculate DOD based on continuous day of a month. My concern is I would like to calculate only those Order Date. For example, I would like to compare Sales on 4/12/2016 and 1/12/2016. ((50-20)/20).
How should i amend the query to achieve that?
You have to create a calculated column to get the previous date:
Previous Date =
CALCULATE (
MAX ( [Order Date] ),
FILTER ( ALL ( 'Table' ), [Order Date] < EARLIER ( 'Table'[Order Date] ) )
)
Then just create the measures with the following expressions:
Sales Volume := SUM('Table'[Sales])
Sales Volume Prev :=
CALCULATE (
SUM ( [Sales] ),
FILTER ( ALL ( 'Table' ), 'Table'[Order Date] = MAX ( [Previous Date] ) )
)
Sales Volume (DOD) :=
DIVIDE ( [Sales Volume] - [Sales Volume Prev], [Sales Volume Prev] )
Let me know if this helps.

MDX Calculation for summing the product of two measures and multiplying that by the last children of two other metrics

Here is a snip of my cube's dimension usage:
In "TD Measures" I have
[A] "Billable Client Hours Current".
In "Personnel Measures" I have
[B] "FTE Count" (an employee's amount they are working like .5 for
people who work 20 hours per week)
[C] "Forecast FY End" Forecast for the end of the fiscal year
[D] "Forecast FYTD" Forecast for the current period to date in the fiscal year.
The calculation I need to do at a leaf level is:
[A][B][C]/[D]
The issue is that [A] has more dimensionality that [B], [C], and [D].
So If this is my data:
The calc I need to do is:
((15*.05)+(5*1)) //sum of hours in a period multiplied by that month's FTE
X 2000/300 //last child of FCFYE divided by last child of FCFYTD in the currently selected set.
This calc is likely to change a little over the next week or two, but this is the main concept of what they are looking to do. Any help in writing the MDX for this to create a calculated member in my cube is greatly appreciated. Sorry if I've left out any key info--I'm quite the MDX noob.
Through digging through Chris Webb's and Mosha's posts as well as working with some guys on the MSDN forums I have worked out a solution to this below. Ultimately, I worked out with the business that we didn't need to interrogate the underlying rows to discern if they were active or not since the addition of the root functionality eliminated the need as long as they filtered on it from DimMiscellaneous. But for the sake of helping someone with a similar problem here is the full MDX below.
//Only evaluate if they are active
CREATE HIDDEN UtilizedFTESummator;
[Measures].[UtilizedFTESummator] = Iif([Measures].[Is Active For Utilization Value] > 0,[Measures].[Period FTE],NULL);
NON_EMPTY_BEHAVIOR([Measures].[UtilizedFTESummator]) = [Measures].[Is Active For Utilization Value];
//only include this measure if the underlying employee has values in their underlying data for active in utilization
CREATE MEMBER CURRENTCUBE.[Measures].[FTE Active Utilization]
AS
SUM
(
EXISTING [Historical Personnel].[Employee Id].[Employee Id],
[Measures].[UtilizedFTESummator]
),VISIBLE=0;
//Show weighted FTE by workdays
CREATE MEMBER CURRENTCUBE.[Measures].[FTE MTD Active Utilization]
AS SUM
(
DESCENDANTS([Historical Personnel].[Employee Id].CURRENTMEMBER,[Historical Personnel].[Employee Id].[Employee Id]),
(
DIVIDE
(
SUM
(
DESCENDANTS([Period].[Fiscal Period].CURRENTMEMBER,[Period].[Fiscal Period].[Fiscal Period]),
[Measures].[FTE Active Utilization]*[Measures].[Work Days In Month]
)
,SUM(ROOT([Historical Personnel].[employee id].currentmember),[Measures].[Work Days In Month])
,0
)
)
);
//Use Weighted FTE for calculating the weighted value for each person (all periods aggregated)
//Forecast Billable End Of Year has default aggregation of last child
CREATE MEMBER CURRENTCUBE.[Measures].[Annualized CBH Projected]
AS DIVIDE
(
SUM
(
DESCENDANTS([Historical Personnel].[Employee Id].CURRENTMEMBER,[Historical Personnel].[Employee Id].[Employee Id]),
[Measures].[Billable Client Hours Current] *
(
DIVIDE
(
[Measures].[Forecast Billable End Of Year]
,
[Measures].[Forecast Billable FTE]
,0
)
)
*[Measures].[FTE MTD Active Utilization]
)
,[Measures].[FTE MTD Active Utilization]
,0
);
Simplified answer with the users filtering on the Is Active For Utilization flag is as follows:
//Weight FTE by employee calculating FTE * workdays for each period and then dividing by the sum of days irrespective of filters on historical personnel or miscellaneous
CREATE MEMBER CURRENTCUBE.[Measures].[FTE MTD]
AS SUM
(
DESCENDANTS([Historical Personnel].[Employee Id].CURRENTMEMBER,[Historical Personnel].[Employee Id].[Employee Id]),
(
DIVIDE
(
SUM
(
DESCENDANTS([Period].[Fiscal Period].CURRENTMEMBER,[Period].[Fiscal Period].[Fiscal Period]),[Measures].[Period FTE]*[Measures].[Work Days In Month]
)
,
SUM((ROOT([Historical Personnel].[employee id].currentmember),ROOT([Miscellaneous]),[Measures].[Work Days In Month]))
,0
)
)
);
//Weight by FTE with default agg for Forecast EOY being last child.
CREATE MEMBER CURRENTCUBE.[Measures].[Annualized CBH Projected]
AS DIVIDE
(
SUM
(
DESCENDANTS([Historical Personnel].[Employee Id].CURRENTMEMBER,[Historical Personnel].[Employee Id].[Employee Id]),
[Measures].[Billable Client Hours Current] *
(
DIVIDE
(
[Measures].[Forecast Billable End Of Year]
,
[Measures].[Forecast Billable FTE]
,0
)
)
*[Measures].[FTE MTD]
)
,[Measures].[FTE MTD]
,0
);

Restore original filter context in DAX formula

I have a data model with a table called Transactions (below), and TranDate which is the date dimension.
I have a measure to calculate the opening balance for the first date that is visible in the pivot table.
Op Bal First Selected :=
VAR MinDate = CALCULATE (
MIN ( TranDates[Tran Date] ),
ALLSELECTED ( TranDates )
)
RETURN
CALCULATE (
SUM ( Transactions[Amount] ),
FILTER
(
ALL ( TranDates ),
TranDates[Tran Date] < MinDate
)
)
If I deselect Jan-16, I get the desired result below:
However, the measure only works in Excel 2016 and not Excel 2013, because variables are not supported in Excel 2013. If I replace the MinDate variable with the DAX expression, then the measure will return blanks because ALLSELECTED restores the context in the FILTER() function and not the context in the CALCULATE() function (i.e. MinDate is 1-Jan instead of 1-Feb).
Is there an equivalent DAX formula that works in Excel 2013 / SSAS 2014 (i.e. without using variables)?
After lots of trial and errors, here's the measure I defined:
Op Bal First Selected:=
MINX
(
ADDCOLUMNS (
ADDCOLUMNS
(
SUMMARIZE (
ALL(Transactions),
Transactions[Tran Date]
),
"MinDate",
CALCULATE (
MIN ( Transactions[Tran Date] ),
ALLSELECTED()
)
),
"Op Bal First Selected Calc",
CALCULATE (
SUM ( Transactions[Amount] ),
FILTER
(
ALL( Transactions ),
Transactions[Tran Date] < [MinDate]
)
)
),
[Op Bal First Selected Calc]
)
I used ALL() in the inner context so that the original filter context (i.e. pivot table selection) is preserved in the context just outside of ALLSELECTED().
If you want to use the TranDate table as the filter, you can define it as follows:
Op Bal First Selected:=
MINX
(
ADDCOLUMNS (
ADDCOLUMNS
(
SUMMARIZE (
ALLSELECTED(TranDates),
TranDates[Tran Date]
),
"MinDate",
CALCULATE (
MIN ( TranDates[Tran Date] )
)
),
"Op Bal First Selected Calc",
CALCULATE (
SUM ( Transactions[Amount] ),
FILTER
(
ALL( TranDates ),
TranDates[Tran Date] < [MinDate]
)
)
),
[Op Bal First Selected Calc]
)

Calculating Avg Orders per day using MDX

I am trying to create a calculated member which should returns the averages orders per week per person.
Below is the screen shot where the client will be looking to forecast the work load. Staff may not work all the days in a week.
The calculation will be : No of Orders / No of scheduled days in that week.
It would not be very hard to calculate this if the week name is in the same hierarchy of the date, but in this case it is not in hierarchy but just member of the dimension.
This is the MDX I've tried:
Avg ( Descendants
( [Date Planned].[Date Planned].CurrentMember, [Date Planned].[Date Planned].[Date Planned] ),
[Measures].[Orders Qty] )
It would be much easier when you have week and day added into the hierarchy, but if you don't have possibility to have this added, there is different non elegant solution.
If you would assume that this member will always be used with Week on rows your member calculation would be as follow:
This will work correctly only with weeks on rows - so I would recommend to extend your Calendar hierarchy by week and day and then we can have a chat about much more elegant solution.
Try using this:
WITH MEMBER [Measures].[avg_week] AS
Avg ( EXISTING { [Date Planned].[Week Of Year].[Week Of Year] },
[Measures].[Orders Qty] )
SELECT [Measures].[avg_week] ON COLUMNS,
NON EMPTY
{ [Person].[PersonName].[PersonName] * [Date Planned].[Week Of Year].[Week Of Year] } ON ROWS
FROM [Your cube]
Let me know if this can help you.
Maybe something like the following:
WITH
MEMBER [Measures].[PlannedDayCnt] AS
Count
(
Exists
(
(EXISTING
[Date Planned].[Date Planned].[Date Planned].MEMBERS)
,[Date Planned].[Week Of Year].currentmember
)
)
MEMBER [Measures].[Averge Orders] AS
[Measures].[Orders Qty] / [Measures].[PlannedDayCnt]
SELECT
{
[Measures].[Orders Qty]
,[Measures].[PlannedDayCnt]
,[Measures].[Averge Orders]
} ON 0
,
[Person].[PersonName].[PersonName]
* [Date Planned].[Week Of Year].[Week Of Year] ON 1
FROM [aCube];
I'd like to test but unsure how to model your scenario in the AdvWrks cube.
I would first want to see how many "dates" belong to the week. That would be easy as it would be those days when Orders were placed for that person that week.
NonEmpty
(
[Date Planned].[Date Planned].[Date Planned].MEMBERS,
(
[Date Planned].[Week Of Year].currentmember,
[Person].[PersonName].currentmember,
[Measures].[Orders Qty]
)
)
Now that you have the requisite dates for the "current" week and the "current" person, you would need to calculate the average order quantity for these set of dates. It would look like this:
AVG
(
NonEmpty
(
[Date Planned].[Date Planned].[Date Planned].MEMBERS,
(
[Date Planned].[Week Of Year].currentmember,
[Person].[PersonName].currentmember,
[Measures].[Orders Qty]
)
)
, [Measures].[Orders Qty]
)
Your final construct would need to be:
WITH MEMBER Measures.AverageOrderPerDay AS
AVG
(
NonEmpty
(
[Date Planned].[Date Planned].[Date Planned].MEMBERS,
(
[Date Planned].[Week Of Year].currentmember,
[Person].[PersonName].currentmember,
[Measures].[Orders Qty]
)
)
, [Measures].[Orders Qty]
)
SELECT
{
[Measures].AverageOrderPerDay,
[Measures].[Orders Qty]
}
ON 0,
[Person].[PersonName].[PersonName].MEMBERS
* [Date Planned].[Week Of Year].[Week Of Year].MEMBERS ON 1
FROM [YourCube]