MDX: get attribute from a slowly changing dimension in a cell - ssas

I need to build a report that shows day-to-day changes in the cube. E.g. for account we show the balance on day X and balance on day Y. I achieve it with something like this:
WITH
MEMBER OldBalance AS ([Balance], [Date].[Date].[2013-05-01]) -- start date
MEMBER NewBalance AS ([Balance], [Date].[Date].[2013-05-04]) -- end date
SELECT {OldBalance, NewBalance} ON COLUMNS
[Account].[AccountNumber].[AccountNumber] ON ROWS
FROM TheCube
This shows two columns for each account, everyone's happy:
OldBalance NewBalance
ACT123 1050.25 1048.29
ACT345 950.08 1421.92
In addition to account number, [Account] dimension also has SalesRepName as an attribute, and the value of SalesRepName may change over time, making [Account] a slowly changing dimension. What I want to see is something along the lines of:
OldBalance NewBalance OldSalesRep NewSalesRep
ACT123 1050.25 1048.29 John Smith John Smith
ACT345 950.08 1421.92 John Smith George Fisher
But I have no idea how to achieve this in MDX, and whether it is even possible.

The trick is to use something like TopCount and then Item:
WITH
MEMBER [Date].[Date].StartDate AS [Date].[Date].[2013-05-01]
MEMBER [Date].[Date].EndDate AS [Date].[Date].[2013-05-04]
MEMBER OldBalance AS ([Balance], [Date].[Date].StartDate)
MEMBER NewBalance AS ([Balance], [Date].[Date].EndDate)
MEMBER OldSalesRep AS
TopCount(
NonEmpty(
([Account].[SalesRep].[SalesRep], [Date].[Date].StartDate,
[Account].[AccountNumber].CurrentMember), [Balance]),
1)
.Item(0).Item(0).Properties("Caption")
MEMBER NewSalesRep AS
TopCount(
NonEmpty(
([Account].[SalesRep].[SalesRep], [Date].[Date].EndDate,
[Account].[AccountNumber].CurrentMember), [Balance]),
1)
.Item(0).Item(0).Properties("Caption")
SELECT {OldBalance, NewBalance, OldSalesRep, NewSalesRep} ON COLUMNS
[Account].[AccountNumber].[AccountNumber] ON ROWS
FROM TheCube
Keep in mind, however, that on large cubes the performance may be not that good.

Related

MDX OLAP Cube Query Optimization

Problem: I'm trying to write a MDX query that will show the first date a member has measure values.
Data obstacles:
1. I don't have access to the data warehouse/source data
2. I can't request any physical calcs or CUBE changes
Looking for: I know this goes against what a CUBE should be doing, but is there any way to achieve this result. I'm running into locking conflicts and general run time issues.
Background: After some trial and error. I have a working query but sadly it's only is practical when filtered for <10 employees. I've tried some looping but there are ~60k employee ids in the cube with each one having 10-20 emp keys (one for each change in their employee info).
//must have values for measure 1 or 2
WITH
set NE_measures as
{
[Measures].[measure1] ,
[Measures].[measure2]
}
//first date with measure values for each unique emp key
MEMBER [Measures].[changedate] AS
Head
(
NonEmpty([Dim Date].[Date].[Date].allMEMBERS, NE_measures)
).Item(0).Member_Name
SELECT non empty {[Measures].[changedate]} ON COLUMNS,
non empty [Dim Employee].[Emp Key].[Emp Key].allmembers ON ROWS
FROM [Cube]
Try this:
MEMBER [Measures].[changedate] AS
Min(
[Dim Date].[Date].[Date].allMEMBERS,
IIF(
NOT(ISEMPTY([Measures].[measure1]))
OR NOT(ISEMPTY([Measures].[measure2])),
[Dim Date].[Date].CurrentMember.MemberValue,
NULL
)
);
I’m assuming the KeyColumn or ValueColumn is more likely to sort properly than the name. So if MemberValue doesn’t work then try Member_Key.
The most efficient way of accomplishing this would be to add a date column in the fact table with measure 1 and measure 2 then create a AggregateFunction=Min measure on it. But you said you couldn’t change the cube so I didn’t propose that superior option.

MDX with snowflaked dimensions

I have an ordinary DimProduct which has a snowflaked DimPriceList where I store for each ProductKey different prices for the products.
In a MDX, depending on certain product properties, I would like to display different prices for the products. The MDX would look something like this.
CASE
WHEN [Dim Product].[Value Group].CurrentMember.MEMBERVALUE = '02' THEN
CASE
WHEN [Dim Product].[Stock Account Nr].CurrentMember.MEMBERVALUE = 101 THEN
([Dim Price List].[Sales1])
WHEN [Dim Product].[Stock Account Nr].CurrentMember.MEMBERVALUE = 102 OR
[Dim Product].[Stock Account Nr].CurrentMember.MEMBERVALUE = 103 THEN
([Dim Price List].[Valuation])
ELSE
0
END
ELSE
1
END
How can I now access the current membervalue of the DimPriceList? I just get 'All' as result and not the actual value for the current member. I've also tried [Dim Price List].[Valuation].CurrentMember.MEMBERVALUE but with no success. Appreciate any sort of help or hints.
You get the [All] member because it IS the default value. In absence of any scope, the engine bases it's calculation around the default member. If you want the output to change based on the current member of Product, you should attempt at creating a calculated member. Encapsulate the logic above into the script which chooses the requisite measure depending upon the current member. I am assuming you must be having Sales1 and Valuation in form of Measure in your cube. If that is the case your calculated member should choose the requisite measure based on the MEMBERVALUE or you can employ
....
[Dim Product].[Stock Account Nr].CurrentMember IS [Dim Product].[Stock Account Nr].&[101]
....clause.
That said, you need to give some scope.

MDX show all sales until now

i have a huge table of cashflows that means there are +int values for income and -int values for outcome.
I have MeasureGroup for Sum the amount of money.
I now want to display not only the sum of money per month but also the sum of all the past time until the current month so like that:
Month MoneyAmount Total
1 20 20
2 -10 10
3 5 15
4 -10 5
So i know for the first part its just like
select [Measures].[Money] on 0,
[Date].[Month].Members on 1
From MyCube
but how can i add the sum column?
i thought about something like SUM( { NULL : [Date].[Month].CurrentMember } , [Measures].[Money] ) but that didnt work as well :(
In MDX, the total is already there. You do not have to do complex calculations to get it.
But it depends on your exact hierarchy structure how the All member is called. If you have a date user hierarchy named [Date].[Date], and it has a month level named [Date].[Date].[Month], then the all member of the hierarchy would probably be called something like [Date].[Date].[All]. If [Month] is an attribute hierarchy of the Date dimension, then the "all member" would probably be called [Date].[Month].[All]. In the latter case, the all member would already be the first member of the set [Date].[Month].Members. As you are asking the question, I am assuming this is not the case, and you are using a user hierarchy. Then you could change your MDX query to
select [Measures].[Money] on 0,
Union([Date].[Month].Members, { [Date].[Date].[All] }) on 1
From MyCube
Please note that you can change the name of the All member in the property settings of a dimension when designing an Analysis Services dimension, hence I cannot know the definitive name without knowing the details of this setting in your cube. So you might have to adapt the name of the all member.
You can find this name out in SQL Server Management Studio in an MDX window as follows: open the hierarchy that you are using, and then open the "Members" node, below which you should find the "All Member". You can drag this into your MDX statement, and the proper name will appear there.
As in a running sum?
You need a calculated measure, like this:
With Member [Measures].[Running Sum] as Sum( ( [Date].[Months].Members.Item(0) : [Date].[Months].CurrentMember ), [Measures].[Money])
Select [Date].[Months].Members on Rows,
{[Measures].[Money], [Measures].[Running Sum] } on Columns
From [MyCube]

Member with Named set returns always the same value in SSAS

I'm needing to query a cube as a plain table. Also, i need to use a named set for performance reasons (the query takes 10x if not using the set). The issue is that i'm getting the same value for every row for the Date Time calculated member. BTW, i'm using this member cause i haven't found any way to query a named set 'on columns'.
The query looks like this:
with
set [CurrentDates] as filter([Time].[Date].Members, not isempty([Measures].[Net Sold Units]))
member [Measures].[Date Time] as [CurrentDates].Item(1).Member_Key
select
{
[Measures].[Date Time],
[Measures].[Song Name]
--other calculated members
}
on columns
,
subset
(
{
order
(
except
(
NONEMPTY([Trend Transaction].[Trend Transaction].Members, [Measures].[Net Sold Units]),
[Trend Transaction].[Trend Transaction].[All]
),
[Measures].[Date Time], basc
)
}
,0, 50)
on rows
from Trends
where
(
{[Time].[Date].&[2012-09-01T00:00:00],[Time].[Date].&[2012-09-02T00:00:00]}
)
And the result i'm getting looks like this:
Date Time Song Name
9/1/2012 Where Have You Been
9/1/2012 We Are Young
9/1/2012 Wide Awake (Origionally Performed by Katy Perry) [Karaoke Version]
9/1/2012 Breathing
9/1/2012 So Sophisticated (Originally Performed by Rick Ross) [Karaoke Version]
.
.
.
The dates for the last songs is obviously wrong, should e 9/2/2012
I recognize that i'm kinda SSAS newbie, probably there is something i'm missing here :)
Is there any way to do that i'm needing?
Thanks in advance!
Your calculated : member [Measures].[Date Time] as [CurrentDates].Item(1).Member_Key
will always refer to the second item in your set (remember it is 0 based )
What you want is to use the RANK function: this with the CURRENTMEMBER function brings back the item position in the Set as the set is rendered. e.g. with:
set [CurrentDates] as filter([Time].[Date].Members, not isempty([Measures].[Net Sold Units]))
member MemberRank As 'RANK(Time].[Date].CURRENTMEMBER , CurrentDates)'
member [Measures].[Date Time] as [CurrentDates].Item(MemberRank-1).UNIQUE_NAME
Well, the solution was finally to have the set and the member like this:
set CurrentDates as filter([Time].[Date].[Date], not isempty([Measures].[Net Sold Units]))
member [Measures].[Date Time] as CDATE(NONEMPTY(CurrentDates, [Measures].[Net Sold Units]).Item(0).Member_Key)
The key is to have the named set into the SCOPE, to have it referenced in the member.

SSAS & OLAP cube: twice same measure

I'm not very experienced in OLAP Cube + MDX, and I'm having a hard time trying to use twice the same measure in a cube.
Let's say that we have 3 Dimensions: D_DATE, D_USER, D_TYPE_OF_SALE_TARGET and 3 tables of Fact: F_SALE, F_MEETING, F_SALE_TARGET
F_SALE is linked to D_USER (who make the sale) and D_DATE (when)
F_SALE_TARGET is linked to D_USER, D_DATE, D_TYPE_OF_SALE_TARGET (meaning: user has to reach various goals/targets for a given month).
I can browse my cube:
Rows = Date * User
Cols = Number of sale, Total amount of sale + the value of 1 target (in the WHERE clause, I filter on [Dim TYPE SALE TARGET].[Code].&[code.numberOfSales])
How can I add other columns for other targets? As all the targets are in the same table, I don't see how to add a second measure from [Measures].[Value - F_SALE_TARGET] linked to a different code, ie. [Dim TYPE SALE TARGET].[Code].&[code.amountOfSale].
your question is not clear to me but it seems like one way to accomplish that is by creating Calculated Members. Basically, select you cube in BIDS, go to the Calculations tab and create Calculated Members. You would be able to insert your MDX query there. For each target type you can create a different calculation such as: ([Measures].[Value - F_SALE_TARGET], [Dim TYPE SALE TARGET].[Code].&[code.amountOfSale])