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.
Related
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
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.
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
)
)
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
How can I compute average of sums in MDX? I want to compute sum of spending for each person and then compute an average of it. I have the following query so far, but I believe it gives me wrong result:
WITH MEMBER [Measures].[Average] AS
AVG(Measures.cost)
SELECT [Measures].[Average] ON COLUMNS
FROM
( SELECT Measures.cost ON COLUMNS,
{Person.[Last name].MEMBERS}*
{Person.[First name].MEMBERS} ON ROWS
FROM Cube )
Any help would be greatly appreciated.
You just need to put in the first argument of Avg the set of your persons.
WITH MEMBER [Measures].[Average] AS
AVG(Person.[Last name].MEMBERS * Person.[First name].MEMBERS, Measures.cost)
SELECT [Measures].[Average] ON COLUMNS
FROM Cube
Try to create a calculated measure for this function like this
IIF (([Measures.cost] > 0), AVG(Person.Members,Measures.cost),null)
Then use this calculated measure in your MDX query
SELECT Person, 'calculated.measure'
FROM Cube
This is only a sample code to illustrate the function.