I've not much experience with multidimensional cubes, SQL and Tabular modeling are more my thing.
I'm trying to create a calculated measure that's a running total across time periods (months). The trouble is, I'm not using a traditional date dimension because this "Period" dimension has an "Opening balance" category. This is a requirement set by the customer.
The [Dim Period] table is pretty simple, it has a key which is starts at 201800 and goes through to 201812. 201800 being the opening period. I've tried to create a simple hierarchy, though there are no attributes lower than the Period.
So far I've come up with this;
WITH MEMBER [Measures].[YTD Total] AS
Aggregate
(
PeriodsToDate
(
[Dim Period].[Period Hierarchy].[Period],
[Dim Period].[Period Hierarchy].CurrentMember
),
[Measures].[Total]
)
SELECT
{[Measures].[Total], [Measures].[YTD Total]} ON COLUMNS,
{[Dim Period].[Period Hierarchy].[Period]} ON ROWS
FROM
[My Cube]
This returns the same value in the [Total] and [YTD Total] column, so I'm obviously doing something wrong.
For reference, here's a measure I created in a Tabular model that does work;
YTD Total:=CALCULATE([Total],FILTER(ALL(DimPeriod[Period]),DimPeriod[Period]<=MAX(DimPeriod[Period])))
Any pointers would be greatly received.
I think I've found the answer;
WITH MEMBER [Measures].[YTD Total] AS
Aggregate
(
PeriodsToDate
(
[Dim Period].[Period Hierarchy].[(All)],
[Dim Period].[Period Hierarchy].CurrentMember
),
[Measures].[Total]
)
SELECT
{[Measures].[Total], [Measures].[YTD Total]} ON COLUMNS,
{[Dim Period].[Period Hierarchy].[Period]} ON ROWS
FROM
[My Cube]
Related
I'm learning MDX and having trouble with SCOPE.
As a test I'm trying to create a new measure only for Fiscal Year 2011 but
have a syntax error.
It isn't a Create Calculated Measure in SSAS Script but a query in SSMS.
Any help or pointers would be great.
WITH MEMBER [Measures].[Test Scope]
AS 1
(
SCOPE ([Measures].[Test Scope]);
SCOPE ([Date].[Fiscal Year].&[2011]);
THIS = [Measures].[Reseller Order Quantity] + 10000;
END SCOPE;
END SCOPE;
)
SELECT
{[Measures].[Reseller Order Quantity],[Measures].[Test Scope]} ON COLUMNS
,[Date].[Fiscal Year].[Fiscal Year].MEMBERS ON ROWS
FROM [Adventure Works]
Query (4, 2) Parser: The syntax for 'SCOPE' is incorrect.
You can’t use a scope statement in a query. It has to be defined in the MDX script of the cube or run in the context of a session. The most common way to handle this is the following.
WITH MEMBER [Measures].[Test Scope] AS
IIF(
[Date].[Fiscal Year].CurrentMember is [Date].[Fiscal Year].&[2011],
[Measures].[Reseller Order Quantity] + 10000,
NULL
)
SELECT
{[Measures].[Reseller Order Quantity],[Measures].[Test Scope]} ON COLUMNS
,[Date].[Fiscal Year].[Fiscal Year].MEMBERS ON ROWS
FROM [Adventure Works]
There is also very old MDX syntax CELL CALCULATION in an MDX query which I would recommend not using without through testing since it is infrequently used. Off the top of my head it would look like this. It could “scope” over any measure or calculated measure or tuple. Here we have scoped over a null calculated measure.
WITH MEMBER [Measures].[Test Scope] AS
NULL
CELL CALCULATION [Test Scope Calc]
FOR '([Measures].[Test Scope],[Date].[Fiscal Year].&[2011])'
AS '[Measures].[Reseller Order Quantity] + 10000'
SELECT
{[Measures].[Reseller Order Quantity],[Measures].[Test Scope]} ON COLUMNS
,[Date].[Fiscal Year].[Fiscal Year].MEMBERS ON ROWS
FROM [Adventure Works]
Here is my mdx :
SELECT {[Measures].[Amount],[Measures].[Amount]} ON COLUMNS
FROM (select ({[Dim Date].[Date Int].&[20130119] : [Dim Date].[Date Int].&[20130114]}) ON COLUMNS
FROM [terst])
WHERE ([Dim Client].[Common Client Name].&[Test])
CELL PROPERTIES VALUE, FORMAT_STRING, LANGUAGE, BACK_COLOR, FORE_COLOR, FONT_FLAGS
this two measures have identical output, since both should only containt amount between two dates 20130119 and 20130114.
What shall i do if the second measure in the mdx should containt amount between 2 different dates for example (20140116 and 20140616) but still be in the same mdx request?
To see if I understand the request, you want to be able to display two date ranges for the same measure side by side, as single columns? If so you need two custom members that are aggregates of the date range requested, and then use them to select from the measure like so:
With Member [Date].[FirstPeriod] as
aggregate(
{[Dim Date].[Date Int].&[20130119]:[Dim Date].[Date Int].&[20130114]})
Member [Date].[SecondPeriod] as
aggregate(
{[Dim Date].[Date Int].&[20140119]:[Dim Date].[Date Int].&[20140114]})
select {([Measures].[Amount],[Date].[FirstPeriod]), ([Measures].[Amount],[Date].[SecondPeriod])} on 0
from [terst]
where ([Dim Client].[Common Client Name].&[Test])
Hope that's what you needed :)
I need to product a report from my cube that looks something like the following.
(dummy data)
Where it lists sales and gross profit for today, this week, the period and year to date across the products category.
My cube is setup as follows
A date dimension
And the cube itself
Currently I have not implemented the product category pieces.
I'm struggling with how to write an MDX query that can return the sales/gross profit for a single day and then week and so on.
I can return it by itself like so
SELECT {[Measures].[Gross Profit],[Measures].[Price]} ON COLUMNS
From [Cube]
WHERE [Date].[Date Key].[2015-04-22];
and so on for the other various types (week etc), but I'm unsure as how to apply the where filter to the columnn itself rather than the overall query, or if this is even the correct way to do it and I should be making multiple MDX calls that I then compose in my app that will use this.
Can anyone give me a pointer in the right direction here?
EDIT: Seems to mostly work using the approach #Akshay Rane described however I cannot get one of my measures to work
MEMBER [This Week] as
(PeriodsToDate([Date].[Fiscal Week Date].[Fiscal Week],StrToMember('[Date].[Fiscal Week Date].[Date Key].&[' + '20140401' + ']'))
,[Measures].[Merchandise Gross Profit])
Gives me an error:
The function expects a string or numeric expression for the argument. A tuple set expression was used.
Any pointers here?
You will have to create separate Calculated Members for each time interval you want to aggregate the data upon.
This can be done in [Adventure Works] cube as follows.
WITH
MEMBER [Today] as
([Measures].[Internet Sales Amount], [Date].[Date].CURRENTMEMBER)
MEMBER [Last Week] as
AGGREGATE (
{ [Date].[Date].CURRENTMEMBER.lag(6) : [Date].[Date].CURRENTMEMBER }
, [Measures].[Internet Sales Amount]
)
SELECT
{ [Today], [Last Week] } ON 0,
{ ([Product].[Product Categories].[Category], [Date].[Date].[Date]) } ON 1
FROM
(
/*FILTERING ON SPECIFIC DATE USING SUBCUBE*/
SELECT [Date].[Date].&[20070715] ON 0
FROM [Adventure Works]
)
If you can take the different levels of date from the same user hierarchy then something like this is possible:
SELECT
{
[Date].[Calendar].[Month].&[2006]&[7]
,[Date].[Calendar].[Date].&[20050220]
}
*
{
[Measures].[Order Quantity]
,[Measures].[Internet Sales Amount]
} ON COLUMNS
,{[Product].[Category].Children} ON ROWS
FROM [Adventure Works];
The above produces results like this:
What is the most efficient way to do this in MDX? I know you can create 2 calculated measures, having active with the time dimension current period selected, and another having the previous period, and then do a filter with a complex condition.
However what about other functions which may be more efficient? Any recommendations?
My goal is to create a set of calculated measures, which would help customer analysts. The main 2 dimensions, for these are [Calendar], and obviously [Customer]. I have a fact, which contains activity for customers. These are the 3 entities that our calculations would be based on.
This is from an article by Chris Webb: http://cwebbbi.wordpress.com/2010/10/08/counting-new-and-returning-customers-in-mdx/
With a follow up article on how to optimize it: http://cwebbbi.wordpress.com/2013/06/28/optimising-returning-customers-calculations-in-mdx/
WITH
MEMBER MEASURES.[Returning Customers] AS
COUNT(
NONEMPTY(
NONEMPTY(
[Customer].[Customer].[Customer].MEMBERS
, [Measures].[Internet Sales Amount])
, {[Measures].[Internet Sales Amount]}
* {NULL : [Date].[Calendar].CURRENTMEMBER.PREVMEMBER}
)
)
MEMBER MEASURES.[New Customers] AS
[Measures].[Customer Count] – MEASURES.[Returning Customers]
SELECT
{[Measures].[Customer Count]
, MEASURES.[Returning Customers]
, MEASURES.[New Customers]} ON 0,
[Date].[Calendar].[Calendar Year].MEMBERS ON 1
FROM [Adventure Works]
I have this:
SELECT
NONEMPTY(
[Date].[Calendar].[Calendar Year].MEMBERS
)
*
[Measures].[Internet Sales Amount] on 0,
ORDER(
[Customer].[Customer Geography].[State-Province].MEMBERS
,[Measures].[Internet Sales Amount]
,BDESC)
on 1
from [Adventure Works]
What is the most efficient way of ordering descending by the last date column - this should be dynamic so that it still works when we go over month end.
I would use
ORDER(
[Customer].[Customer Geography].[State-Province].MEMBERS
,([Measures].[Internet Sales Amount]
,Tail([Date].[Calendar].[Calendar Year]).Item(0).Item(0)
)
,BDESC)
and assume that the added term Tail([Date].[Calendar].[Calendar Year]).Item(0).Item(0) can be calculated by Analysis Services just checking the time dimension, and does not need any dynamic context, and hence should be fast.
If you want to have an expression which is independent of the content of the columns, you can use:
ORDER([Customer].[Customer Geography].[State-Province].MEMBERS
,Tail(Axis(0)).item(0)
,BDESC)