I looked at this topic, Calculating the number of days in a time dimension node - with Grand Total, but can't seem to get it.
I have a Time Dimension; [Invoice Date].
I want to count the number of Work Days in that dimension for a specified time period. I'm new to MDX.
Here's what I have.
Count(
Descendants(
[Invoice Date].CurrentMember,
[Invoice Date].[Work Date].[Work Date]
)
)
I'm getting a cube error now.
An easy way to implement this reliably would be to create a physical measure "Day Count". To do this, create a new measure group on the Date dimension table, and define "Day Count" as the Count. On the dimension usage tab, make sure you set a relationship from this measure group to the Invoice Date cube dimension and not the other dimensions.
Related
Would much appreciate any help on this.
I have a measure called "Sales" populated with values, however i am trying to turn the "Sales" value to 0, whenever the "Sales Flag" is set to 0.
Important Note: The Sales Flag is based on Date (lowest level of detail).
The difficulty that i am really experiencing and cant get a grip on, is how i am trying the display the MDX outcome.
As explained above, i would want to make the "Sales" value 0 whenever we have a 0 in the "Sales Flag" (which is based on the Date), but when I run the MDX Script I would wan't on the ROWS to NOT display the Date, but instead just the Week (higher Level to Date), as below shows:
I really have spent hours on this and can't seem to understand how we can create this needed custom Sales measure based on the Sales Flag on the date level, but having the MDX outcome display ROWS on Week level.
Laz
You need to define the member in the MDX before the select. Something like that:
WITH MEMBER [Measures].[Fixed Sales] as IIF([Sales Flag].currentMember=1,[Sales], 0)
SELECT [Measures].[Fixed Sales] on 0, [Sales Flag] on 1 from [Cube]
I am writing the code without SSAS here so it might not be the 100% correct syntax but you can get the general idea ;)
You can add the iif in the SELECT part but I find creating member to be the cleaner solution.
SELECT IIF([Sales Flag].currentMember=1,[Sales], 0) on 0, [Sales Flag] on 1 from [Cube]
If you have a control over the cube in SSAS you can create a calculated member there and you can access it easier.
Glad to hear if Veselin's answer works for you, but if not...
Several approaches are also possible.
Use Measure expression for Sales measure:
Use SCOPE command for Day level (if it's Key level of Date dimension). If it's not a key level you have to aggregate on EVERY level (week, year etc) to emulate AggregateFunction of Sales measure but with updated behavior for one flag:
SCOPE([Date].[Your Date Hierarchy].[Day].members,[Measures].[Sales]);
THIS=IIF([Sales Flag].CurrentMember = 1,[Measures].[Sales],0);
END SCOPE;
Update logic in DSV to multiply Sales column by SalesFlag. This is the easiest way from T-SQL perspective.
Let's assume i have easy table with sales data like:
id shop
id product
date
amount
Can you help me to write MDX query for calculated member to get current period sales ratio to same period of previous year?
For example, if month or quarter selected as one of dimensions.
Let's assume you've a [Time] dimension with [Year], [Month] and [Day] levels.
If
SELECT
[Time].[Jan 2015]:[Time].[Dec 2015] on 0,
[Measures].[Sales] on 1
FROM
[Cube]
Returns the sales for all months of 2015. We can add a calculated measure to get ratio :
WITH
MEMBER [Sales Ratio] AS DivN(
[Sales],
( ParallelPeriod( [Time].[Year], 1, [Time].current ), [Sales] )
SELECT
[Time].[Jan 2015]:[Time].[Dec 2015] on 0,
{[Sales],[Sales Ratio]} on 1
FROM
[Cube]
DivN is icCube specific and allows for dividing being 'empty' safe.
ParallelPeriod is a standard MDX function, that returns previous years month. You could also use Lag(-12), that is 'travelling' backwards in a level 12 times.
current (aka Currentmember) is also standard MDX and allows for retrieving the current value of a hierarchy/ dimension.
In icCube I'd add a function to navigate to the previous year so you can reuse it (and fix one if needed). Like :
WITH
FUNCTION timePrevYear(t_) AS ParallelPeriod( [Time].[Year], 1, t_ )
MEMBER [Sales Ratio] AS DivN(
[Sales],
( timePrevYear( [Time].current ), [Sales] )
SELECT
[Time].[Jan 2015]:[Time].[Dec 2015] on 0,
{[Sales],[Sales Ratio]} on 1
FROM
[Cube]
It's going to be a bit too much but eventually you could add this kind of calculations in what we call in MDX Utility or Stats dimension, so you can even let the end-user select this in a dropdown from a reporting tools. More on this here.
In the models I create for my clients, I sometimes take another route as ic3 has suggested:
Especially when there will be lots of additional calculations on top of these (e.g. year-to-date, inception-to-date, month-to-date etc).
This is:
load the same facts data again, but set as the "load date" the "date" - 1 year (e.g. mySQL: DATE_ADD(,INTERVAL -1 YEAR).
Advantages:
drill through on history is possible
lots of formulas can be added "on top" of these, you always know that the basics are ok
I have a fact table which stores for each record an init_year and end_year as integers, which refer to the year range in which the record is valid.
In which way I can design a MDX query to select my measures (count) for each year, in order to have a trend of my measures over year?
THANKS
I'm not sure this should be done in MDX.
This sort of thing is usually calculated in the fact tables (linked to a dimension table of all available years), and a new measure is created. No calculation would be done in MDX; you'd just display the new measure.
Having said that, I've just Googled "MDX count start end date" and found www.purplefrogsystems.com/blog/2013/04/mdx-between-start-date-and-end-date which suggests you use the LINKMEMBER function. Their example code was...
AGGREGATE(
{NULL:LINKMEMBER([DATE].[Calendar].CURRENTMEMBER
,[START DATE].[Calendar])}
* {LINKMEMBER([DATE].[Calendar].CURRENTMEMBER
, [END DATE].[Calendar]):NULL}
, [Measures].[Project COUNT])
...or...
AGGREGATE({NULL:[DATE].[Calendar].CURRENTMEMBER}
, [Measures].[Project COUNT])
...but it needs careful reading!
I have a calculated measure that needs to cross join Customer and Product dimension then cross join a total sales measure to get a percentage for a specific customer sale.
[Measures].[Sale Value] / [Measures].[Total Sales]
each measure has a link to the time dimension, and are set to last non empty.
The problem is that as I look at more information over longer periods (days, months, years etc) it gets slower and slower and slower. I am assuming this is because the calculated measure does its processing on the fly and there is no caching.
Is this correct? I have about 2000 customers and 50 products.
Please please help! any information about how to speed this up would be great.
The answer to this was to set a many to many relationship between Customer/Prodcut and the [Measures].[Total Sales] measure group.
I'm relatively new to MDX (in the process of ordering a book just now) and having a crack at creating a calculated measure, which should sum a value from one of my Fact tables, based on a set range of dates (from my Time dimension) which should be filtered by an attribute from another dimension. Unfortunately, I seem to have gotten myself in a bit of a situation and can't see a clear way out. I looked through other similar questions but didn't see any trying to do this same thing, only single dimension measures.
I have a Measure Group, which contains the physical measure SourceMeasure.
I have a Time dimension, named [Time], which I want to use to specify my range for the calculation. This is related to the above measure group by my Date Key.
I have an Account dimension, named [Dim Account], which contains two date attributes: [Account Start Date] and [Account End Date]. This is related to the above measure group via an Account ID.
What I'm trying to do, is filter the [Time] dimension to a range based on the [Account Start Date] and [Account End Date], and return the sum of [SourceMeasure] for the period specified for that account.
Obviously, this will be different for each account, so shouldn't be aggregated, except by the [Dim Account] dimension (perhaps returning 0 or null if not applied).
Example test expression below, this is currently not working due to an error with the FORMAT_STRING syntax (according to MDX Studio).
WITH
MEMBER [Measures].[LifetimeMeasure] AS
Sum
(
{
StrToMember
(
"[Time].[Date].&["
+ Format([Dim Account].[Account Start Date].CurrentMember.MemberValue,"yyyy-MM-ddThh:mm:ss")
+ "]"
)
:
StrToMember
(
"[Time].[Date].&["
+ Format([Dim Account].[Account End Date].CurrentMember.MemberValue,"yyyy-MM-ddThh:mm:ss")
+ "]"
)
}
,[Measures].[SourceMeasure]
)
SELECT
{
[Measures].[LifetimeMeasure]
,[Measures].[SourceMeasure]
}
ON COLUMNS
,{
[Dim Account].[Account].[AccountName]
}
ON ROWS
FROM
[MyCube]
I've tried a few different approaches (SCOPE, Filter, IIF) but every time I seem to get back to the same sticking point - how to filter the [Time] dimension based on the value of the [Dim Account] start and end dates.
Now, it may be that I'm completely misunderstanding how the relationships work between the dimensions and/or how calculated measures are computed by SSAS but I'm not yet at a level where I'm sure what to look for, so I'm going round in circles.
Is what I'm trying to do possible, and if so, any pointers as to where to look to help me figure out where I'm going wrong? Should I perhaps be looking to use a Calculation Dimension instead?
I hope this all makes sense, let me know if I've missed anything or if more detail is required. I'm testing using MDX Studio.
I found the error by adding the CONSTRAINED flag to the StrToMember function.
It seems that my [Time] dimension's date entries have defaulted to the time "00:00:00" while my [Dim Account] dimension's date entries have defaulted to "12:00:00". It looks like a mismatch between 24-hour and 12-hour clock. My date fields on the [Dim Account] dimension are marked as "Regular", not "Date" due to the fact that the dimension isn't a natural time dimension. I think it's potentially this that's causing the mismatch.
To workaround the issue for now, I've removed the Time format from my Format expression and just appended the "00:00:00" to the string while I search for the root cause. I'll update once I've solved it.
UPDATE: The cause of the mismatch is not in the dimension, but in the format string I've used in the StrToMember expression. It's not documented on MSDN, but the following string outputs 12-hour time format:
"yyyy-mm-ddThh:mm:ss"
While this string outputs 24-hour time format:
"yyyy-mm-ddTHH:mm:ss"