MDX calculated member total - mdx

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!

Related

SQL - SUM two columns with a date range on one of the columns

First off its been a long week and I'm having a moment e.g. I just can't figure this out but I know its straight forward.
I have a CTE with a query for a GL Detail and one for Budget which are bought together to display all the details needed for a report.
For example the GL detail bring back the actual amount from a date range such as 2019-01-01 and 2019-04-01
and the budget part brings back the budget for each month so the date range is 2019-01-01 and 2019-12-01 as I need to sum up the total budget in a report.
Using an iif expression in SSRS the report shows the actuals up to the month a user select (there is on a to_date parameter)such as April then the report shows actual from Jan and then budget from May to Dec. I need to show the total of budget for the 12 month which is straight forward as I have bought each month amount back.
My question is I need to sum the GL actual amount for the months selected in by the user Jan to April and the remaining budget amounts May to Dec. For some reason I just can't work it out in my head.
Edit - I'm using
postgresql
SSRS - Microsoft SQL Server Reporting Services
columns are in GL is gldetail.amount and for Budget budget.amount_budget - I have a column in both gldetail and budget queries which is called post_date.
Worked it out -
,case
when src.post_date <= src._to_date then src.amount
when src.post_date > src._to_date then src.amount_budget
end as actual_budget_total
Then in the report sum the actual_budget_total

MDX - Average over the whole time period, even when no data exists

I have a fact table with 1 row for each day. Example:
ID Date Value
1 20190101 10
1 20190102 15
2 20190101 31
If I take a simple Value average in SSAS cube I get:
ID Average <Formula>
1 12.5 (10+15)/2
2 15.5 31/2
As I understand, 15.5 is there because in total there are 2 days in the scope as only two days exist in the fact data when I select the whole month.
However, I need to calculate a monthly average instead. It should check that there are 31 days in that month (based on Date dimension) and get this result:
ID Average <Formula>
1 0.8 (10+15)/31
2 1 31/31
So far I've tried to create some "fake rows" if my data, for example I've tried to create rows with Value = 0 for dates 20190103-20190131 for ID=1.
This works, it forces the calculation for ID=1 to always take all days in the period, but it messes up my other calculations in the cube.
Any other ways to force average calculation in SSAS multidimensional cube to always calculate for the entire month?
If you want to do the calculation in the Cube, you can use the Descendants function on your Date dimension
For eg., the following gives the number of days in a month using the AdventureWorks sample
WITH MEMBER Measures.DayCount AS
Descendants
(
[Date].[Calendar].CurrentMember,
[Date].[Calendar].[Date],
LEAVES
).Count
SELECT [Measures].[DayCount] ON 0,
[Date].[Calendar].[Month].ALLMEMBERS ON 1
FROM [Adventure Works]
I would recommend:
select id, eomonth(date) as eom,
sum(value) * 1.0 / day(eomonth(date)) as average
from t
group by id, eomonth(date);
EOMONTH() returns the last day of the month. You can extract the day to get the number of days in the month.
The * 1.0is because SQL Server does integer division. Your numbers look like integers, but if you are getting 15.5, then you actually have numerics or something other than an integer.

MDX - Calculated MTD measure returning null value

I have a Cube with a Date dimension hierarchy (Year,Semester,Quarter,Month,Day).
There are 2 measures available in the datawarehouse.
[AUD DLY] : Daily numbers
[AUD YTD] : Daily incremental YTD numbers
Hierarchy is as follows
Date - Dimension
Financial - Hierarchy
Year - [Date].[Financial].[Year]
Semester - [Date].[Financial].[Semester]
Quarter - [Date].[Financial].[Quarter]
Month - [Date].[Financial].[Month]
Day - [Date].[Financial].[Day]
Measures [AUD DLY]
Measures [AUD YTD]
I need to add a MTD field in the measures such that when the business select a particular date on their slicer in excel for e.g., 3 March 2016, MTD should be calculated as either of the following ways :
1) [AUD MTD] should be calculated by subtracting [AUD YTD] on
last day of previous month from the current selected date.
So if we select 3 March 2016 then
[AUD MTD] = [AUD YTD] on 3 March 2016 - [AUD YTD] on 29 Feb 2016
OR
2) [AUD MTD] should be calculated by adding the [AUD DLY] from first day
of the current month until the selected date in that month.
So if we select 3 March 2016 then
[AUD MTD] = SUM ([AUD DLY] from 1 March 2016 to 3 March 2016)
I created a New Calculated Member from Calculations tab in the Cube designer in the BIDS 2010. The MDX query is below. However when I try to browse the cube the [AUD MTD] values are only returning nulls.
Can someone please help what am I doing wrong ?
CREATE MEMBER CURRENTCUBE.[Measures].[AUD MTD]
AS Aggregate
(
PeriodsToDate
(
[Date].[Financial].[Month]
,[Date].[Financial].CurrentMember
)
,[Measures].[AUD DLY]
),
FORMAT_STRING = "Currency",
NON_EMPTY_BEHAVIOR = { [AUD DLY] },
VISIBLE = 1 , DISPLAY_FOLDER = 'AUD Values' , ASSOCIATED_MEASURE_GROUP = 'Measures' ;
Also the business would be using the new calculated measure in excel using the Slicer, they want to select any date and be able to view the MTD value for that month.
Also can someone please help with MDX query for both methods (1) and (2) ?
Your help much appreciated.
I think the problem with your quoted code (method 2) is that [Date].[Financial].CurrentMember must be at a level at or below the [Date].[Financial].[Month] level. Otherwise PeriodsToDate returns an empty set.
So the problem is not in your calculated member definition, but somewhere in the query in which it's being used. In that query, [Date].[Financial].CurrentMember may be returning a member at a level above Months. Hard to see without seeing the query itself.
Method (1) is more fiddly. You can get the last day of the previous month with
Ancestor([Date].[Financial].CurrentMember,[Date].[Financial].[Month]).PrevMember.LastChild
but you'd have to build in some logic for days in the first month of the financial year, which would otherwise subtract the value for a previous fin year from this year's YTD value. So I'd recommend method (2).
As far as I know selecting a date (I mean a date, not a month) in the Excel slicer will make that date the .CurrentMember. I'm a bit hesitant because Excel does generate some deeply bizarre MDX sometimes.
EDIT: Another possible problem is a hierarchy mismatch. You can select a perfectly good Day in a date hierarchy, but if it isn't in exactly the hierarchy you specify in your calculated member definition, you can get weird results. IMHO more recent versions of SSAS encourage a proliferation of attribute hierarchies and multiple "real" hierarchies, making this a real problem.
As a test can you please add this very simple measure to make sure that currentmember is behaving as expected:
CREATE MEMBER CURRENTCUBE.[Measures].[AUD MTD]
AS [Date].[Financial].CurrentMember.member_caption
If when you use the above all it returns is the All member then you know something is wrong.
You need to double-check your relationships and datatypes used within your date hierarchies as this is often the reason for time calculation problems.
This is an alternative to your measure but I suspect if the original script is not working then neither will this...
CREATE MEMBER CURRENTCUBE.[Measures].[AUD MTD]
AS SUM
(
MTD([Date].[Financial].CurrentMember)
, [Measures].[AUD DLY]
)

Group by months in a time hierarchy using MDX

I have a dimension with the following levels:
Years
Months
Days
I want to get some data by months regardless of the year, i.e. weddings in January.
If I have:
January 2011 - 43
January 2012 - 20
January 2013 - 30
What I want is:
January - 93
Is it possible?
Thanks
Edit:
I have tried this query (with sales, no weddings):
WITH member [Time].[example] AS 'AGGREGATE({[Time].[Months].[Jan]})'
SELECT
NON EMPTY {Hierarchize({[Measures].[Sales]})} ON COLUMNS,
NON EMPTY {[Time].[example]} ON ROWS
FROM [SteelWheelsSales]
but I only get the first January.
Yes, this depends on how you structured your calendar dimension. In this case, you would have a month string field, and it would have
January
February
... So on... Note that the month string field, does not have the year included.
This field would be aggregatable set in the SSAS dimension. When creating your MDX query you would put month on rows, and weddings on columns. Using this approach you should get your desired result.
So doing the following should get you all January sales :
SELECT
NON EMPTY {[Measures].[Sales]} ON COLUMNS,
NON EMPTY {[Time].[Year] * [Time].[Jan]} ON ROWS
FROM [SteelWheelsSales]

MDX Last Child with Filter

I am using the following calculation in my cube to get balances for P&L and Balance Sheet accounts. this is working fine but the problem is that this code doesn't work if I have filters on the date dimension.
For example, let's say I am looking at amounts for the 4 quarters for 2014 - the sub-total in this case for balance sheet accounts would be the Amount in 2014 Q4(and the calculation works correctly). However, if when am looking at say two quarters Q1 and Q2 for 2014, the calculation still shows the sub-total as the Amount in 2014 Q4 whereas the correct value should be Amount in 2014 Q2. I have pasted a screen shot of Excel pivot table also.
CASE [Accounts].[Account Type].CurrentMember.MemberValue
WHEN 'Balance Sheet'
THEN ([Dates].[Hierarchy].currentMember.lastChild, [Measures].[Measures].[Amount])
ELSE Amount
END
Any idea how to achieve this?