Cube: Passing one dimension current member inside the argument of another dimension - mdx

In OLAP cube, while creating calculated measures, is it possible to pass the current member of one dimension (say [Dimension_Two]) as a parameter of Lead() or Lag() functions for another dimension ([Dimension_One])?
Something like this:
Sum( PERIODSTODATE ( [Dimension_One].[All].level,
[Dimension_One].CurrentMember.Lead([Dimension_Two].[Dimension_Hierarcy].CurrentMember)
) ,[Measures].[Cost] )

Related

Using a date range in calculated member in MDX query for Tabular cube model

I have a requirement where I have to get the values of different measure with each measure having its own date range, the following query works and gets me the data over an year,
WITH MEMBER [Measures].[Ex1] AS ([Measures].[Average Spending], [Date].[Year].&[2020])
MEMBER [Measures].[Ex2] AS ([Measures].[Average Time Spent], [Date].[Year].&[2019])
SELECT {[Customer].[Name].[Name]} ON 1, {[Measures].[Ex1],[Measures].[Ex2]} ON 0 FROM [Model];
but when I try to pass a date range instead of year, I'm getting an error,
WITH MEMBER [Measures].[Ex1] AS ([Measures].[Average Spending], [Date].[Year].&[2020])
MEMBER [Measures].[Ex2] AS ([Measures].[Average Time Spent], [Date].[Date].[01-May-2020]:[Date].[Date].[31-May-2020])
SELECT {[Customer].[Name].[Name]} ON 1, {[Measures].[Ex1],[Measures].[Ex2]} ON 0 FROM [Model];
I'm getting the following error,
Executing the query ... The function expects a string or numeric
expression for the argument. A tuple set expression was used. Run
complete
How do I get the measure for a date range for each calculated member?
If you do not use a tuple (i. e. a combination of single members of the hierarchies like Measures or Year), but a set, then you need to tell MDX what to do with the set elements to get to a single value. I would assume the following will give what you want:
WITH
MEMBER [Measures].[Ex2] AS
Aggregate([Date].[Date].[01-May-2020]:[Date].[Date].[31-May-2020],
[Measures].[Average Time Spent]
)
...
Instead of Aggregate, you could also use Sum, Avg, Variance etc. but normally, I prefer using Aggregate, as this uses whichever aggregation method is defined for the measure in the cube, i. e. it is more universal, and the query does not need to be adapted to changes in the cube calculation scripts.
See also Aggregate in the SSAS documentation

Force calculated member to entire cube

I'm trying to add a calculated member to my cube, which will return the first fiscal year where there is any data at all in a particular measure.
The purpose is to suppress (i.e. NULLify) various year-on-year calculated measures when the year is this first year: in that year, comparison with the previous year is meaningless.
I've got this so far:
WITH MEMBER Measures.DataStartYear_Sales
AS
HEAD(
NONEMPTY([Calendar].[Fiscal Periods].[Fiscal Year].Members,[Measures].[QuantityOrdered])
,1).Item(0).Properties("NAME")
At the moment:
a. It's a query-scoped measure, as that's easier to experiment with.
b. It returns the first year's Name, as that's easier to see. Eventually I'll just return the member itself, and do an IS comparison against the year hierarchy .CurrentMember in the other calculated member calculations.
The problem I expected, which has happened, is that I only want this measure to be calculated once, over the whole cube. But when I used it in a query, it obviously reacts to the context. For example, if I stick the Products dimension on ROWS, the value of this measure will be different for each row, because each product's earliest order date is different.
That is of course useful, but it's not what I want. Is there some way to force this measure to ignore the query context, and always return the same value?
I looked into SCOPE_ISOLATION and SOLVE_ORDER, but they don't do what I'm trying to do here.
I suppose I could specify a tuple of Dimension1.All, Dimension2.All.... DimensionN.All, covering all dimensions in the cube, but that seems messy and fragile.
I think you might be able to accomplish this with static sets. Here is an example using Adventure Works that produces the same first year regardless of context:
WITH STATIC SET FirstYear AS
HEAD
(
NONEMPTY([Date].[Calendar Year].[Calendar Year].MEMBERS, [Measures].[Internet Sales Amount])
, 1
)
MEMBER FirstYearName AS
FirstYear.ITEM(0).NAME
SELECT
[Measures].[FirstYearName] ON COLUMNS
, [Date].[Calendar Year].[Calendar Year].MEMBERS
//Add as many dimensions as you like here...for example
* [Product].[Product].[Product].MEMBERS
ON ROWS
FROM
[Adventure Works]
;
Example output:
That should hopefully put you on the right track.

How to filter time hierarchy based on anothr attribute's value in MDX

I want to create a calculated member. I have a time dimension hierarchy" YQM", which has Year/Quarter/Month. The calculated member should find YTD till the current month. However, the value of current month will come from database.
I have created a attribute, "CP" which returns the current month value.
Please tell me how to create the calculated member. Please note "CP" is not in the same hierarchy YQM.
I don't understand why you are using Aggregate. So, I will assume that it is there for some purpose, which you have't clarified. Now, if the members of [YQM].[Month] and [Dim].[CP] are of the same format, then you can try the code below:
Aggregate(
PeriodsToDate([Dim].[YQM].[Month].MEMBERS,
FILTER([Dim].[YQM].[Month].MEMBERS,
[YQM].[Month].CURRENTMEMBER.member_value = [Dim].[CP].FirstChild.member_value)
)
)
Why not try playing with the function YTD. The following should give you the monthly amount in the first column of data and then the YTD amount in the next column:
WITH MEMBER [Measures].[YearToDate] AS
AGGREGATE(
YTD()
,[Measures].[someMeasureInCube]
)
SELECT
{
[Measures].[someMeasureInCube],
[Measures].[YearToDate]
} ON 0,
[Dim].[YQM].[Month].MEMBERS ON 1
FROM [yourCube]

Using percentile as measure in SSAS

How do I use percentile (let's say 99% percentile) as a measure in SSAS cube? I'd like to be able to report on it using many different dimensions and filters so pre-calculating in sql is not an option.
If you want to evaluate percentiles over a dimension, then you can do it without having to pre-calculate anything in SQL. This can be done using a combination of the TopPercent and Tail MDX functions.
For example, say you want to find the 25th percentile over a [Date].[Calendar Month] dimension attribute by the [Measures].[Avg Daily Census] (I work in health care) measure. You could use the following query to do this.
WITH
MEMBER [Measures].[25th Percentile] AS
(
Tail(
TopPercent(
[Date].[Calendar Month].[Calendar Month],
100 - 25,
[Measures].[Avg Daily Census]
)
).Item(0),
[Measures].[Avg Daily Census]
)
SELECT
[Measures].[25th Percentile] ON 0
FROM [Census]
This query uses TopPercent to find the top 75 percent of values along the [Calendar Month] dimension attribute, finds the member with the lowest value along that set, and then evaluates the measure at that member.
Now, if you want to generate the entire set of percentile values, you can use a sequence utility dimension (just a dimension containing numbers), or you could create a custom percentile dimension containing 0-99. The following query would generate the values of the measure over all percentages.
WITH
MEMBER [Measures].[Percentile] AS
(
Tail(
TopPercent(
[Date].[Calendar Month].[Calendar Month],
100 - [Sequence].[Ones].CurrentMember.MemberValue,
[Measures].[Avg Daily Census]
)
).Item(0),
[Measures].[Avg Daily Census]
)
SELECT
[Measures].[Percentile] ON 0,
[Sequence].[Ones].&[0] : [Sequence].[Ones].&[99] ON 1
FROM [Census]
However, if you are trying to evaluate percentiles at the grain of the fact table, then I believe you will either need to pre-calculate the percentile values for each fact row or add a degenerate dimension and use the method above.

How to groupby and filter on the same dimension in MDX

I want to create a barchart with a bar for each month and some measure.
But i also want to filter on a range of day which might not completly overlap some of the month.
When that happen I would like the aggregate count for those month to only aggregat over the days that fall in my date range not get the aggregate for the whole month.
Is that possible with MDX and if it is how should the request look like?
Create a second time dimension, using a virtual dimension of the original dimension. Use one dimension in the WHERE and another in the SELECT.
This often happens anyway if some people want 'Business Time' of quarters and periods, and others prefer months. Or if you have a financial year which runs April-April.
You can use subselect. You can find more information on this page and this page:
When a member is specified in the axis clause then that member with
its ascendants and descendants are included in the sub cube space for
the subselect; all non mentioned sibling members, in the axis or
slicer clause, and their descendants are filtered from the subspace.
This way, the space of the outer select has been limited to the
existing members in the axis clause or slicer clause, with their
ascendants and descendants as mentioned before.
Here is an example:
SELECT { [Customer].[Customer Geography].[Country].&[Australia]
, [Customer].[Customer Geography].[Country].&[United States]
} ON 1
, {[Measures].[Internet Sales Amount], [Measures].[Reseller Sales Amount]} ON 0
FROM ( SELECT {[Customer].[Customer Geography].[Country].&[Australia]
, [Customer].[State-Province].&[WA]&[US]} ON 0
FROM [Adventure Works]
)
The result will contain one row for Autralia and another one for the United States. With the subselect, I restricted the value of United Stated to the Washington state.
One way I found to do it with Mondrian is as follow
WITH MEMBER [Measures].[Units Shipped2] AS
SUM
(
{
exists([Store].[Store Country].currentmember.children,{[Store].[USA].[WA],[Store].[USA].[OR]})
},[Measures].[Units Shipped]
)
MEMBER [Measures].[Warehouse Sales2] AS
SUM
(
{
exists([Store].[Store Country].currentmember.children,{[Store].[USA].[WA],[Store].[USA].[OR]})
},[Measures].[Warehouse Sales]
)
SELECT
{[Measures].[Units Shipped2],[Measures].[Warehouse Sales2]} ON 0,
NON EMPTY [Store].[Store Country].Members on 1
FROM [Warehouse]
I am not sure if the filtering will be done in SQL like below and give good performance or be run locally
select Country, sum(unit_shipped)
where state in ('WA','OR' )
group by Country