MDX: Slice by measure? - mdx

In MDX, is it possible to slice one measure by another?
E.g. suppose I have a cube which includes two measures: Order Value ($) and Order Quantity (#). Can I write a query that will tell me the number of orders with an order value over $1000?

I'd suggest two ways:
Add Order Value as separate dimension and filter out all values which are less than $1000.
Add Order dimension and filter them out with a calculated measure.
MDX formula:
SUM(
existing [OrderDim].[OrderHier].[OrderAttr].Members,
IIF(
[Measures].[Order Value] > 1000,
1,
Null
)
)

Related

Calculated measure to find the datediff using timedimension

I need to find out the number of days in Month based on Time dimension. Time dimension is Month when Jan is selected it has to return 31 as value.
If you have Time dimension and Time hierarchy, this should work:
WITH MEMBER measures.NumOfDays AS
Count
(
Descendants
(
[Time].[Time].CurrentMember,
,LEAVES
)
)
SELECT Measures.NumOfDays ON 0,
[Time].[Time].Month on 1
FROM [MyCube]
The below sample shows how to get the count.
Please note the below query only show the idea how to do this. Your cube will note have these attributes you you need to replace them
with member
measures.t as Count(([Date].[Month of Year].&[1],[Date].[Day of Month].[Day of Month].members))
select {measures.t}
on columns
from [Adventure Works]

SSAS count of non zero measure

I am newbie to SSAS cube and need some help. I have a cube created from a fact table and one of the measure, lets call it amount, contains zeros. This measure was created as a SUM.
Now I also have the Count measure added by SSAS designer.
What I need is the count of all non zero amount.
I tried to add a calculated measure as
`IIF([Measures].[amount] > 0,[Measures].[RowCount],null)`
also tried
FILTER([Measures].[RowCount],[Measures].[Amount] > 0)
Both these returns the count including the amount=0.
I am validating it via SSMS sql query
SELECT count(*)
FROM [dbo].[Fact_Session]
where SiteKey = 5 and DateKey = 20170201
and Amount >0
Any help is appreciated. My assumption is that the IIF/Filter statement will operate on the individual rows before cubing, as once aggregated into a dimension, the amount will not be 0 due to the aggregation . Please Help.
To count non-zero you can use this approach:
WITH
MEMBER [Measures].[IsNotEmpty] AS
IIf(
Not(IsEmpty([Measures].[Amount]))
,1
,Null
)
But better to do this inside a SUM over a particular set - so the following counts how many subcategories are not empty:
WITH
MEMBER [Measures].[SubCategory_IsNotEmpty] AS
SUM(
[Product].[Product Categories].[SubCategory].members
,IIf(
Not(IsEmpty([Measures].[Amount]))
,1
,Null
)
)

Median function in MDX (Pentaho Mondrian)

I am trying to implement the Median function in MDX. In particular I want to calculate the median of the measure "Amount" for every member of the dimension "Region". For this, I first wrote the following MDX query:
with member [measures].[X] as median([Regions].members, [measures].[Amount])
select {[Regions].members} on rows,
{[measures].[X]} on columns
from [product]
However the above query will calculate the average "Amount" for every member of "Region" and then return the median of these (average) values.
To fix the issue I rewrote the above query using a "Productid" dimension that assigns a unique id to each product of the cube:
with member [measures].[X] as median([productid].members, [measures].[Amount])
select {[Regions].members} on rows,
{[measures].[X]} on columns
from [product]
The above query correctly returned the median "Amount" values for every member of "Region". The problem is that the query seems to be computationally expensive and it hangs. I was wondering if there is a more elegant solution to the problem.

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