DAX Dynamic Total with Power View - powerpivot

I am attempting to graph, via Power View, the sum of all account balances at various points in time, so that I can see how the total is changing.
I do not have transaction history (add / subtract), only 'Balance' at a specific point in time for each account.
A simplified example of my data is:
Account Date Balance
a111 01 January 2015 100
a111 01 February 2015 150
b222 01 March 2015 200
c333 01 March 2015 300
b222 01 May 2015 150
d444 01 June 2015 400
As far as I can tell, I need to create a measure to generate a dynamic rank per 'Account', ordered by latest date. I should then be able to create a second measure to SUM each account where the rank = 1.
There is a similar example of this issue discussed in the question PowerPivot DAX - Dynamic Ranking Per Group (Min Per Group), however I cannot seem to get this to display how I want on a line graph in Power View.
What I want to display on the line graph is (letting the graph sort out the missing dates):
Date Balance
01 Jan 2015 100 -- Account a111 only
01 Feb 2015 150 -- Account a111 only, but the new value
01 Mar 2015 650 -- Accounts a111 (latest), b222 and c333
01 May 2015 600 -- As above, but account b222 is updated
01 Jun 2015 1000 -- Latest values for all accounts
However, what I am currently seeing is:
Date Balance
01 Jan 2015 100 -- Sum of Balances matching this date
01 Feb 2015 150 -- As above
01 Mar 2015 500 -- As above
01 May 2015 150 -- As above
01 Jun 2015 400 -- As above
The problem, as far as I can tell, is that at each data point in the graph, the 'filter context' is reducing down to only the rows that match the date, whereas I need all rows on on before that date with a 'rank' of 1.
For reference, I am using Excel 2013 and the data is ultimately coming in via Power Query (pulling data from SharePoint), so I can work some magic there if necessary (i.e. generating a numeric 'group id' for use with DAX MAX() function, as that doesn't seem to like strings).
I hope this is not to confusing, and thanks in advance for any help.

The solution to this is to have a separate date dimension table so balance can be independently calculated on a per-month basis without respect to the fact table.
Let's assume you have a date table called Date.
So, first create the base measure
[Total Balance] := SUM( FactTable[Balance] )
Next we calculate the first month in the fact table to use as a floor for looking through our Date table values.
[First Ever Balance Date] := FIRSTDATE( ALL( FactTable[Date] ) )
And now we determine the last date with a balance for the date range between that first month and the current month in context:
[Last Balance Date] :=
LASTNONBLANK (
DATESBETWEEN ( Date[Date], [First Ever Balance Date], MAX ( Date[Month] ) ),
[Total Balance]
)
So take account a111 in the month of 5/1/2015. This measure will look in all the dates between 1/1/2015 (our [First Ever Balance Date] ) and 5/1/2015 ( the MAX Date[Month] ) , find the last row with a balance and return the corresponding Date[Date] ( 2/1/2015 ).
This measure will return BLANK for any month before an account's initial balance. Using BLANKS in date filtering doesn't work, so we should replace these BLANK values with the [First Ever Balance Date] to ensure the running balance for that account will still return 0.
[Last Balance Date Remove Blanks] :=
IF (
ISBLANK ( [Last Balance Date] ),
[First Ever Balance Date],
[Last Balance Date]
)
Now we can calculate the current balance of any account for any month by looking up the balance as of the Last Balance Date Remove Blanks
[Last Balance] :=
CALCULATE (
[Total Balance],
DATESBETWEEN ( Date[Date], [Last Balance Date Remove Blanks],
[Last Balance Date Remove Blanks] )
)
And finally we use a SUMX across the accounts to add up their individual Last Balance amounts.
[Account Total Balance] := SUMX( ALL( FactTable[Account] ), [Last Balance] )
Now in your pivot table you just put Date[Month] on the rows and [Account Total Balance] as the measure. Note this will include months with no fact table rows like 4/1/2015 in your sample set. If you wish to exclude these, add another intermediate measure to count your fact table rows:
[Fact Table Row Count] := COUNTROWS ( FactTable )
And then create a measure to return BLANK() if [Fact Table Row Count] is BLANK(), and otherwise [Account Total Balance]
[Account Balance Hide Rows] :=
IF (
ISBLANK ( [Fact Table Row Count] ),
BLANK (),
[Account Balance]
)

Related

Filter Table Using Value Selected In Excel Pivot Table Connected to SSAS Cube

I am trying to combine two tables in an SSAS cube and filter one of the tables depending on a value selected by the user in a pivot table from an Excel file connected to the cube. Is this possible and if so how do I do it?
To describe in more detail, I have two tables: history and forecast. For history there is only one set of records for each time period, but there are many forecasts for most periods. When a user selects (in the Excel pivot) a particular forecast version to view, I want to show them all of the forecast records available for that forecast and also history but only for periods that preceded the forecast.
So for example if a user today selects (in the Excel pivot) forecast 1, produced in 2021 Q3, the following is where the records come from:
2021 Q1 - history
2021 Q2 - history
2021 Q3 - forecast
2021 Q4 - forecast
2022 Q1 - forecast
2022 Q2 - forecast
but if a user today selects forecast 2, produced in 2022 Q1, the following is where the records come from:
2021 Q1 - history
2021 Q2 - history
2021 Q3 - history
2021 Q4 - history
2022 Q1 - forecast
2022 Q2 - forecast
Hopefully its clear what I'm trying to accomplish. If this approach won't work but there is another way to accomplish this, please let me know.
Thank you in advance for your help!
Create a new table that is unconnected in the model for the filter that lists your forecast periods. Mine here has a new forecast every quarter.
The start date is the column used to determine whether to use History or Forecast in these DAX measures:
Actual Value = IF(HASONEVALUE('Filter'[Period]),
CALCULATE( SUM(History[Value]), History[Date] < MAX('Filter'[Start date]) ),
"Select quarter")
Forecast Value = IF(HASONEVALUE('Filter'[Period]),
CALCULATE( SUM(Forecast[Forecast]), Forecast[Date] >= MAX('Filter'[Start date]) ),
"Select quarter")
Actual or Forecast Value = IF(HASONEVALUE('Filter'[Period]),
[Actual Value] + [Forecast Value],
"Select quarter")
And here's what it looks like in Excel:

How to get a percentage over the total at each hierarchical level in Analysis Services

I have inherited a multidimensional OLAP cube (SQL Server 2014) and I currently need to extend it to produce the output I need.
Currently, I have a loan book by Report Date and then I need to get the proportion of the loan book by Geography.
An example hierarchy would be:
CY2018 > CY2018 Q3 > Jul CY2018 > Australia > Victoria > 3000
and then display the fields, Current balance and Proportion of Loan Book.
Or, alternatively I might want to see the proportion of loan book for Victoria over the entire loan book on a particular date.
Proportion of loan book is a calculation of the balance at a particular level in the hierarchy divided by the All balance for the loan book on a particular date.
For example:
If you are looking at Feb 2017 and Victoria, then I would like to see the proportion of the loan book for Feb 2017, Victoria over the entire balance for Feb 2017.
If you are looking at April 2018 and postcode 3000, I would like to see the proportion of the loan book for postcode 3000 in April 2018 over the entire balance for April 2018.
If you are looking at Jan 2016 and Australia, then you would see 100%, being the total loan book for that month.
The proportion of the loan book will always be calculated over the current month selected. It makes no sense to calculate a proportion of a loan book over multiple months or quarters etc, but I wouldn't care if that happened as a side-effect of what I am trying to achieve.
At the moment I have created a Calculated Member called Proportion of Loan Book as follows:
Case
When IsEmpty( [Measures].[Current Balance] )
Then 0
Else ( [Geography].[Geography Key].CurrentMember,
[Measures].[Current Balance]) /
( [Geography].[Geography Key].[All],
[Measures].[Current Balance] )
End
This produces something like this:
The problem with this is that it (1) doesn't take into consideration the current month, and (2) only shows a proportional value at the very bottom postcode level. I've fudged the figures here. but Victoria, for example, should show as 36% of the loan book for Jul 2018, whereas at the moment it shows as 100%.
How can I achieve this?
Ok, I have figured it out I think. Here's my code:
Case
When IsEmpty( [Measures].[Current Balance] )
Then 0
Else ( [Geography].[Geography Key].CurrentMember,
[Measures].[Current Balance]) /
( Root([Geography].[Geography Key].[(ALL)].[ALL]),
[Measures].[Current Balance] )
End
I don't know how correct it is; I pretty much stumbled around until something worked!

Months Outstanding DAX Calculation

I think maybe the way I'm asking this question is making it unclear. Here is another attempt:
I am trying to create a measure that counts the number of months it takes to reach an ending accounts receivable balance. As an example, I start with a measure that calculates an ending AR balance which is a calculation of values from different columns and tables and must look at every AR transaction regardless of date (that measure is already available.) What I now need to do is figure out how many months, counting backwards and including any fractional amount, starting with the most recent month (either selected or today's date) it takes to accumulate fees that add up to the ending ar balance. As an example, assuming we're looking at an AR balance at the end of 2016 $1,000:
Ending December AR Balance $1,000
December Fees: $200
November Fees: $300
October Fees: $400
September: $300
Using these values, the Months outstanding would be 3.33 (200 + 300 + 400 + (100/300).)
-- Original Question --
I'm trying to create a measure in DAX that calculates a Months Outstanding value. Essentially, the months outstanding calculation takes the final accounts receivable for an individual and counts back each month that it took to get to that value. As an example, if the final AR balance is $100 and each prior month had AR billings of $25 each month, the months outstanding would be 4 months.
I have come up with something that I believe is a start, but probably isn't even close:
Months Outstanding:=
VAR TotalBalance = [Ending Balance]
RETURN
CALCULATE(
DISTINCTCOUNT('Date'[Month]),
FILTER(
ALL('Date'[Month]),
[WIP Billings] + [AR Billings] < TotalBalance
)
)
In the above example, I'm trying to count the number of months it takes before the sum of WIP Billings and AR Billings exceeds TotalBalance (WIP and AR Billings are simply measures that are the sum of their respective columns.)
Thanks,
Eric
Edit
Here is the calculation for Ending Balance. The fact tables (Billing, Disbursement, Time, BilledDisbursement, BilledFee, MatterCredit) have references to Date, Matters, Clients, and Personnel
WIP Balance:=
ROUND(SUM(Disbursement[ToBillAmount])
+SUM('Time'[ToBillAmount])
-SUM(BilledDisbursement[ToBillAmount])
-SUM('BilledFee'[ToBillAmount])
-SUM('Matter Credit'[WIPBallance]), 2)
End WIP Balance:=
CALCULATE(
[WIP Balance],
FILTER(
ALL('Date'[Period]),
'Date'[Period] <= MAX('Date'[Period])
)
)
Ending AR Balance:=
CALCULATE(
SUM(Billing[ARAmount]),
FILTER(
ALL('Date'[Period]),
'Date'[Period] <= MAX('Date'[Period])
)
)
Ending Balance:= [Ending AR Balance] + [End WIP Balance]

MDX calculated member total

I'm using a calculated member for "previous period" as:
Case
// Test for current coordinate being on (All) member.
When [<<Target Dimension>>].[<<Target Hierarchy>>].CurrentMember.Level Is
[<<Target Dimension>>].[<<Target Hierarchy>>].[(All)]
Then "NA"
Else (
ParallelPeriod
(
[<<Target Dimension>>].[<<Target Hierarchy>>].[<<Target Level>>],
<<Number of Periods>>,
[<<Target Dimension>>].[<<Target Hierarchy>>].CurrentMember
),
[Measures].[<<Target Measure>>]
)
End
// This expression evaluates the difference between the value of the numeric
// expression in the previous period and that of the current period.
(snippet code taken directly from Microsoft suggestion)
It works as expected but when presenting the Totals I get the whole Year total, even if only some months are selected on rows.
So, if I select say year 2015, months Jan to Jun, I get the six correct values for 2014 months but a 2014 grand total instead of the sum of the six presented values.
Any way to get the "correct" sum value? By correct I mean the sum of the selected rows.
Edited to add the actual code:
Case
When [Dim Time].[Calendar].CurrentMember.Level Is [Dim Time].[Calendar].[(All)]
Then "NA"
Else (ParallelPeriod([Dim Time].[Calendar].[Year],
1,
[Dim Time].[Calendar].CurrentMember),[Measures].[Sales])
End
My Dim Time.Calendar has Year-Month-Day as levels. Easy enough :)
When selecting some months the Year total is the Grand total of the year, not the total of the selected months.
When selecting some days, the Month total is the Grand total of the month, not the total of the selected days.
Edited to add example:
Year Month Day Sales previous year Sales
2015 04 03 74,154.56 € 135,156.41 €
Total 04 2,617,045.75 € 135,156.41 €
Total 2015 37,696,665.69 € 135,156.41 €
(unsure if I should post an answer because it's not yet solved, but seems I found the right direction)
Using the suggestions here I defined a dynamic set (at cube definition time using MS SAS):
CREATE DYNAMIC SET CURRENTCUBE.[DynSet] AS [Dim Time].[Calendar]
and a Calculated member (on Excel, easier to test diferent syntax):
count([DynSet])
Now I get 1 as value on all rows, individual ones, subtotals, totals ... instead of the expected days of the selected month and the total sum.
Maybe someone with better MDX knowledge can develop it further.
I added also CM using the examples of the post count(descendants and count(existing( ... of the original [Dim Temps].[Calendar] and this is what I get:
Year Month Day Previous sales Sales CountExisting CountDescendants CountDays
2015 04 03 74,154.56 € 135,156.41 € 1 1 1
04 132,992.88 € 152,179.24 € 1 1 1
05 130,651.80 € 128,971.65 € 1 1 1
Total 04 2,617,045.75 € 416,307.30 € 31 31 1
Total 2015 37,696,665.69 € 416,307.30 € 365 365 1
I cannot understand how to use the new dynamic set as I'm not able to access its components, I expected [DynSet].[Year] [Month] and [Day] to exist so I could use them on my previous period expressions but they don't, so unsure on how to use it for my purpose.
Thks
Edited:
Tried to define
CREATE DYNAMIC SET CURRENTCUBE.[DynSet] AS [Dim Time].[Calendar].[Day]
and now my last column i.e. count([DynSet]) has a value of 3 for all lines.
Still no idea how to use [DynSet] levels ...
It took me almost two weeks, lots of searching hours and a dozen diferent forums, but finally I got a decent answer that solved the problem.
Take a look here
In brief, add a named calculation (not a calculated member) and scope the formula
SCOPE([Measures].[Previous_Sales]);
SCOPE([Dim Time].[Calendar].[Day].MEMBERS);
THIS = ([Measures].[Sales], ParallelPeriod([Dim Time].[Calendar].[Year])) ;
END SCOPE;
END SCOPE;
Simple enough once you know it!

SSAS DAX time intelligence previous year and calculation gives wrong value

We want to show current periods sales versus previous period sales.
To show the previous period we make use of a date dimenion table and the following calculation:
CALCULATE(SalesValueGross; DATEADD(Date[Date]; -1; YEAR))
Unfortunately somehow it shows minor (decimal) differences when comparing years.
The difference get's bigger when we slice to months.
Another issue we have is that this calculation does not seem to work when comparing (for example) week 1 - 2015 with week 1 - 2014.
Any help is greatly appreciated!
When I want to get prior calendar year sales, I use the a formula such as the following:
Cal Prior Yr Sales:=if(HASONEVALUE('Sale Date'[Calendar Year]),
Calculate([Total Sales],
PREVIOUSYEAR('Sale Date'[Date])),BLANK())
The HASONEVALUE just ensures that there is only one year selected so it will know the correct previous year to retrieve.
You can make a series of calculations that will let you use one calc that determines what level of the date hierarchy you are in (assuming you have the fields available in your date table). Here is something I've used in the past, with a fiscal calendar that was different from the normal calendar.
First, the base calculations:
Sales Same Week Prior Year:=
CALCULATE([Total Sales],Filter(All('Sale Date'),
'Sale Date'[Week Key] = max('Sale Date'[Same Week Last Year])))
Sales Same Month Prior Year:=CALCULATE([Total Sales], Filter(All('Sale Date'),
'Sale Date'[Month Seq] = max('Sale Date'[Month Seq])-12))
Sales Same Quarter Prior Year:=CALCULATE([Total Sales], Filter(All('Sale Date'),
'Sale Date'[Quarter Seq] = max('Sale Date'[Quarter Seq])-4))
Sales Prior Year:=CALCULATE([Total Sales], Filter(All('Sale Date'),
'Sale Date'[Fiscal Year] = max('Sale Date'[Fiscal Year])-1))
You can hide all of those calculations and then create one last calculation and leave it visible:
Sales Same Period Last Year:=
if(HASONEVALUE('Sale Date'[Week Key]), [Sales Same Week Prior Year],
if(HASONEVALUE('Sale Date'[Month Key]),[Sales Same Month Prior Year],
if(HASONEVALUE('Sale Date'[Quarter Key]),[Sales Same Quarter Prior Year],
if(HASONEVALUE('Sale Date'[Fiscal Year]), [Sales Prior Year], BLANK()))))
You may need to add a couple of calculated fields to your date table to make it work. I have fields for: [Same Week Last Year], [Month Seq], [Quarter Seq]. Same week last year is an integer field that is yyyyww. Month Seq and Quarter Seq are just autoincrementing integers in chronological order that do not repeat.
My formula for same week last year is
=if('Sale Date'[Week Nbr] = 53, (('Sale Date'[Fiscal Year]-1) * 100) + ([Week Nbr]-1),
(('Sale Date'[Fiscal Year]-1) * 100) + ([Week Nbr]))
I did the sequence numbers in my SQL view, which is the source for the date date. As an example, if my date table starts at 1/1/2010, the month seq for Jan 2010 is 1 and the month seq for Jan 2011 is 13. The quarter seq for Q1 2010 is 1 and the quarter seq for Q1 2012 is 9.
http://www.daxpatterns.com/time-patterns/ is a good read for this topic.