Situation:
I have created calcalated measures in a SQL Server 2012 SSAS multi dimensional model by creating empty measures in the cube and use scope statements to fill the calculation.
(so I can use measure security on calculations as explained here)
SCOPE [Measures].[C];
THIS = IIF([B]=0,0,[Measures].[A]/[Measures].[B]);
I also made a time calculations which I scope for the whole measure group including the calculation above. (as explained here)
I create empty members for the calculations:
--YTD Calculations
CREATE MEMBER CURRENTCUBE.[Calender Calculations].[YTD-1] AS NULL;
CREATE MEMBER CURRENTCUBE.[Calender Calculations].[YTD] AS NULL;
-- MOVING ANNUAL TOTAL Calculations
CREATE MEMBER CURRENTCUBE.[Calender Calculations].[MAT-1] AS NULL;
CREATE MEMBER CURRENTCUBE.[Calender Calculations].[MAT] AS NULL;
--SCOPE MEASUREGROUPMEASURES
I scope the measuregroup on which the calculations will be performed:
SCOPE (MeasureGroupMeasures("Sales")
);
Next I scope the time calculations for the different Time Hierarchys:
SCOPE ([Calender].[Jaar].[Jaar].members,[Calender].[Calender ID].members);
--YTD
([Calender Calculations].[YTD]=
Aggregate(
CrossJoin({[Calender Calculations].[Current Period]},
PeriodsToDate(
[Calender].[Month Hierarchy].[Jaar],
[Calender].[Month Hierarchy].CurrentMember))
)
);
--YTD -1
([Calender Calculations].[YTD-1]=
Aggregate(
Crossjoin({[Calender Calculations].[Current Period]},
PeriodsToDate(
[Calender].[Month Hierarchy].[Jaar],
ParallelPeriod(
[Calender].[Month Hierarchy].[Jaar],1,
[Calender].[Month Hierarchy].CurrentMember))
)
));
--MAT
([Calender Calculations].[MAT]=
Aggregate(
CrossJoin({[Calender Calculations].&[Current Period]},
ParallelPeriod([Calender].[Month Hierarchy].[Month],11,[Calender].[Month Hierarchy].CurrentMember) :
[Calender].[Month Hierarchy].CurrentMember
)));
--MAT-1
([Calender Calculations].[MAT-1]=
Aggregate(
CrossJoin({[Calender Calculations].&[Current Period]},
ParallelPeriod([Calender].[Month Hierarchy].[Month],23,[Calender]. [Month Hierarchy].CurrentMember) :
ParallelPeriod([Calender].[Month Hierarchy].[Month],12,[Calender].[Month Hierarchy].CurrentMember)
)));
--SCOPE Calendar END
END SCOPE;
Close the measuregroup Scope
--SCOPE MEASUREGROUPMEASURES END
END SCOPE;
Results:
When I query the cube by using a ‘base measures’ and the ‘calculated measure’ the results for the time calculations are correct for the base measure but incorrect for the ‘calculated measure’ C because the measure first gets calculated and after that the time calculation is being done, resulting in aggregating the results.
Example:
The current month is April 2015
Every month has a score of 5%.
The YTD measure gives 20% (5% for jan, feb etc.) Which has to be 5%
My question:
How can I change the time calculation or the ‘calculated measure’ so I get the right results?
Related
I've build a MDX calc member that give me the year-to-date (YTD) for budget, however if the user selects multiple months, it returns the total for year. Which I believe is CurrentMember function, but how do it I get the max from the set?
Aggregate(
PeriodsToDate(
[Date].[Fiscal].[Fiscal Year]
,[Date].[Fiscal].CurrentMember
)
,[Measures].[Budget]
)
So when we have a month slicer to select the month, if the end-user selects more then 1 month, then the CurrentMember fails and the parent is used, so the Full Year (FY) is used.
It might be very late to answer this question but hopefully someone else can benefit with the answer.
for this particualr problem you have to create a dynamic set and apply scope to that. check the below MDX.
dynamic set : existing PeriodsToDate(Date].[Fiscal].[Fiscal Year],[Date].
[Fiscal].CurrentMember)
calcualted member : Aggregate( PeriodsToDate( [Date].[Fiscal].[Fiscal Year]
,[Date].[Fiscal].CurrentMember
)
,[Measures].[Budget]
)
apply scope to it scope (Date].[Fiscal].[Fiscal Year],,[Measures].[Budget])
this = aggregate (([dynamic set],],[Measures].[Budget])
end scope
this way u can select a date range without any problem
Kind Regards
mah
I am trying to apply a measure value calculated at the Month level to a dimension contained within that month i.e.
Should look like this:
I've attempted to use a scoping statement so far but with no luck.
SCOPE (
{[Sale].[Sale Year].&[2]:[Sale].[Sale Year].&[7]}
,[Date].[Calendar Month].&[201603]
,[Measures].[Costs Per Sale] );
THIS = ([Date].[Calendar Month].&[201603],[Measures].[Costs Per Sale]);
END SCOPE;
The Aggregated Sales measure is calculated using the Sale Year which unfortunately has not and cannot be linked to the Cost dimension.
Does anyone know how I can apply the Cost Per Sale monthly value to the [Sale].[Sale Year] dimension?
Thanks
Try this -
SCOPE ({[Sale].[Sale Year].&[2]:[Sale].[Sale Year].&[7]} ,[Measures].[Costs Per Sale]);
THIS = ([Sale].[Sale Year].[All],[Measures].[Costs Per Sale]);
END SCOPE;
I've been tasked with a rather odd Time intelligence function by my finance group that I'm trying to puzzle out.
I've been asked with creating a measure within our SSAS Cube to allow for seeing previous quarter to date based on how far we are in the current quarter. But instead of seeing a standard idea of days elapsed currently versus days elapsed previously, they would like to see days remaining versus previous days remaining.
What I mean by that is, take 1/22/2015 for example. We have 48 days remaining in our current quarter, which I have by means of a calculated measure. I need to find the corresponding working day from the previous quarter where it is also at 48 days remaining.
At that point I could create a date range with some aggregate functions off of the first date in the previous quarter to the corresponding date found in the above and come up with what they are looking for.
The best idea I've had so far is to possibly do this in the database section itself, by creating a new column that is essentially the calculated number of days remaining but stored. But at that point I'm not sure how to take a calculated measure in SSAS and filter a previous quarter date member to use that property as it were.
Do you have an utility dimensions in your cube? We have one called TimeCalculations. In there we have things such as CurrentValue, MTDValue, PrevEquivMTD, Past7Days .... I think your new logic would fit in with such a dimension.
Here is an example of PrevEquivQTD against AdvWrks that I just had a play with. Guessing this doesn't really help your scenario but I had fun writing it:
WITH
SET [NonEmptyDates] AS
NonEmpty
(
[Date].[Calendar].[Date].MEMBERS
,[Measures].[Internet Sales Amount]
)
SET [LastNonEmptyDate] AS
Tail([NonEmptyDates])
SET [CurrQ] AS
Exists
(
[Date].[Calendar].[Calendar Quarter]
,[LastNonEmptyDate].Item(0)
)
MEMBER [Measures].[pos] AS
Rank
(
[LastNonEmptyDate].Item(0)
,Descendants
(
[CurrQ]
,[Date].[Calendar].[Date]
)
)
MEMBER [Measures].[PrevEquivalentQTD] AS
Sum
(
Head
(
Descendants
(
[CurrQ].ITEM(0).PrevMember
,[Date].[Calendar].[Date]
)
,[Measures].[pos]
)
,[Measures].[Internet Sales Amount]
)
SELECT
{[Measures].[pos],[Measures].[PrevEquivalentQTD]} ON 0
,[LastNonEmptyDate] ON 1
FROM
(
SELECT
[Date].[Calendar].[Date].&[20050111]
:
[Date].[Calendar].[Date].&[20080611] ON 0
FROM [Adventure Works]
);
Your Date is 1/22/2015. You want the Same Date in Previous Quarter which would be 8/22/2015.
If this is what you want, you will have to use MDX function ParallelPeriod as shown in sample below. Please replace it with your own Dimensions and Cube.
Select
ParallelPeriod
(
[Date].[Calendar Date].[Calendar Quarter], -- Level Expression
1, -- Index
[Date].[Calendar Date].[Date].&[20150122] -- Member Expression
) On 0
From [Adventure Works]
If you want the same date in the following quarter, then replace index 1 with -1.
Cheers
I have to count something in a strange way, and it works in most cases -- both at leaves and at higher levels of aggregation across multiple dimensions. But it doesn't give correctly aggregated values for one specific dimension.
What I have at the moment is ...
CREATE MEMBER CURRENTCUBE.[Measures].[Active Commitments]
AS NULL,
FORMAT_STRING = '#,#',
VISIBLE = 1;
SCOPE (DESCENDANTS([Date Dimension].[Fiscal Year Hierarchy],,AFTER));
[Measures].[Active Commitments] =
iif([Constituent Activity].[Type].currentMember.Properties("Name")="Correspondence",
sum(([Commitment Dates].[Start Date], NULL: [Date Dimension].[Fiscal Year Hierarchy]), [Measures].[Commitment Count]),
sum(([Commitment Dates].[First Funded Date], NULL: [Date Dimension].[Fiscal Year Hierarchy]), [Measures].[Commitment Count]))
- sum(([Commitment Dates].[Stop Date],[Commitment].[Was Commitment Ever Active].[Sometime Active], NULL: [Date Dimension].[Fiscal Year Hierarchy]), [Measures].[Commitment Count]);
END SCOPE;
SCOPE (DESCENDANTS([Date Dimension].[Fiscal Year Hierarchy],,AFTER));
<Similar to above>
As you can see, the complexity is that one type of "commitment" commences at the [Start Date] and others commence at the [First Funded Date].
This fails whenever multiple members of [Constituent Activity] are selected because in such cases the use of currentMember in the SCOPE statement is invalid. For example, the following MDX executes successfully but outputs #Error --
select
[Measures].[Active Commitments] on columns
,[Date Dimension].[Fiscal Year Hierarchy].[Fiscal Year].&[2011\12] on rows
from Compass3
where
{[Constituent Activity].[Description].[XYZ]
,[Constituent Activity].[Description].[ABC]}
I think what I need to encode within the SCOPE statement is the recursive ...
if a single member of [Constituent Activity] is current
then use the calc as defined above
else use [Measures].[Active Commitments] = sum(all selected members of [Constituent Activity], [Measures].[Active Commitments])
... but how would I write that?
Do you have control all the way back to the data warehouse/data source view? Can you add a calculated field to your fact table, so you have [Commitment Active Date] at the cell level? Then you could do much simpler counts in the cube.
I have found that enforcing business rules and doing business calculations in the data warehouse is more efficient and easier in the long run.
I'm setting up a new cube in Analysis Services, and used the Business Intelligence wizard to work out the currency conversion issues. Now this all works perfectly, money is converted at the leaf level and summed up for display in the user's choice of reporting currency.
My problem now is the calculation of liability. For liability, I need to sum up the money in each currency, then convert it using the most recent 'End of Day Rate'. I have 'End of Day Rate' as a LastNonEmpty measure, but I can't see how to avoid the leaf-level conversion as shown below:
// This is the Many to One section
// All currency conversion formulas are calculated for the pivot currency and at leaf of the time dimension
Scope ({ Measures.[Money] } );
Scope( Leaves([Date]) ,[Reporting Currency].[GBP], Leaves([Currency]));
// Convert Local value into Pivot currency for selected Measures that must be converted with Measure rate [End Of Day Rate]
Scope( { Measures.[Money] } )
This = [Reporting Currency].[Local] * Measures.[End Of Day Rate];
End Scope;
End Scope;
// This is the One to Many section
// All currency conversion formulas are calculated for the non pivot currency and at leaf of the time dimension
Scope( Leaves([Date]) , Except([Reporting Currency].[Currency].[Currency].Members, {[Reporting Currency].[Currency].[Currency].[GBP], [Reporting Currency].[Currency].[Currency].[Local]}));
// This section overrides the local values with the Converted value for each selected measures needing to be converted with Measure rate [End Of Day Rate]…
// LinkMember is used to reference the currency from the source currency dimension in the rate cube.
Scope( { Measures.[Money] } );
This = [Reporting Currency].[Currency].[GBP] / (Measures.[End Of Day Rate], LinkMember([Reporting Currency].[Currency].CurrentMember, [Currency].[Currency]));
End Scope;
End Scope; // Leaves of time, all reporting currencies but local and pivot currency
End Scope; // Measures
The [Money] measure is paid in in different currencies, and each currency is keyed to a currency dimension and an 'End of Day Rate.
What is my best plan for calculating the liability? I'm considering replicating the [Money] measure, but it seems wasteful to have extra measures in just to avoid the currency conversion - Plus in the real cube there are several more measures that require the calculation so it won't just be the extra one.
Anyone else faced something similar?
OK so I ended up creating an invisible [Measures].[Money - Liability] which wasn't auto-converted by the above code, and I ended up with the following calculation in the script:
[Measures].[Liability] =
(
SUM
( [Currency].[Currency].[Currency],
SUM
(
{ NULL : [Date].[Date Key].CurrentMember },
(
[Money - Liability]
)
)
/ [Measures].[End Of Day Rate]
)
* (Measures.[End Of Day Rate], LinkMember([Reporting Currency].[Currency].CurrentMember, [Currency].[Currency]))
);