mdx datediff error - sql

select measures.name on 0,
datediff("d", [Fecha].[Date].currentmember.member_value, [Dim Date].[Date].currentmember.member_value) on 1
from cube
Error: Execution of the managed stored procedure datediff failed with
the following error: Exception has been thrown by the target of an
invocation.Argument 'Date1' cannot be converted to type 'Date'
Is there any requirements to do datediff in mdx?
In the dimension these member are defined as datetime, not sure if this influence in anyway the result...
Update: I solved the problem by making the calculation at the datasource view and at the cube I added a measure that I could use in MDX to create the indicator that I needed. Of course this is all using SSAS for testing the result and SSDT for creating the members. I hope this approach helps a lot of people even though i don't know if this is the best case scenario. Happy MDX ;)

By default, the axis will show, not the member_value, but the member name, which is always a string. The Member_Value is a measure.
With Member MyDateDiff as
datediff("d", [Fecha].[Date].currentmember.member_value, [Dim Date].[Date].currentmember.member_value)
Select
(Measures.MyDateDiff, Measures.Name) on 0
(Fecha.Date.Members, [Dim Date].[Date].Members) on 1
From cube
EDIT
I'm still new to this too, but after your comments, I thought I should elaborate on the process I went through to get similar queries right.
First, make sure you are getting the data you think you are. Get those Member_Value measures into the Columns dimension:
With
Member FechaDate as
[Fecha].[Date].currentmember.member_value
Member MyDate as
[Dim Date].[Date].currentmember.member_value
Select
(Measures.FechaDate, Measures.MyDate) on 0
(Fecha.Date.Members, [Dim Date].[Date].Members) on 1
From cube
Are you getting date values? If yes, try out your datediff function. If not, check the dimension definitions. I wouldn't be surprised to find the the ValueColumn of one of your attributes was set to the key field instead of the date value field, or some such thing.

You may need two steps, but the date add method should be fine. The Member approach from Bill is good, but it returns it as a string, not a date object. If it's in the correct format, you should be able to do:
Member MyDate as
DATEDADD("d", 1, VBAMDX!CDate([Dim Date].[Date].currentmember.member_value))
Depending on how your date string ends up formatted, you may have a little more work to do.

Related

Using a date range in calculated member in MDX query for Tabular cube model

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

MDX: Make Measure Value 0 based on flag

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.

How to expose total number of days in each month via OLAP cube

I'd like an easy way of getting the total number of days for each month in the date dimension.
Currently this information is not exposed in our cubes. Therefore I need to write custom mdx such as the following:
WITH
SET [13Mth] AS Tail([Date].[Date - Calendar Month].[Calendar Month].MEMBERS ,13)
SET [m] AS Tail([13Mth])
MEMBER [Measures].[TotalNumDaysMth] AS
Datepart
("D",
Dateadd
("M",1,
Cdate(Cstr(VBA!Month([m].Item(0).Item(0).Lag(1).Name)) + "-01-" + Cstr(VBA!Year([m].Item(0).Item(0).Lag(1).Name)))
)
- 1
)
MEMBER [Measures].[TotalNumDaysMth-1] AS
Datepart
("D",
Dateadd
("M",1,
Cdate(Cstr(VBA!Month([m].Item(0).Item(0).Lag(1).Name)) + "-01-" + Cstr(VBA!Year([m].Item(0).Item(0).Lag(1).Name)))
)
- 1
)
I don't believe our users will need this information within our cube browsing client but from a developer point of view I could do without having to always implement the above.
What approach should we use to make the above data more easily available?
I have always added an attribute to the date dimension "days in month", of type integer. You can hide this attribute, if you do not want to expose the attribute hierarchy to your users.
But you can still use in calculations.
So my advise would be add a proper attribute to your time dimension and base your calculations of on the attributes.
Hope this helps somehow.
I am assuming that in your development scenario, the month will come from Web Service/Front End/SSRS report etc. In any such cases, you can create a measure that will return the count.
Approach 1: Year-Quarter-Month-Date exists
It is a good practice to have a similar hierarchy in place. The following MDX will work:
with set CurrentMonth as
[Date].[Year-Quarter-Month-Date].currentmember
set DatesInCurrentMonth as
descendants(abc, [Date].[Year-Quarter-Month-Date].[Date])
member [Measures].countofdaysinmonth as
count(DatesInCurrentMonth)
select measures.CountOfDaysInMonth on 0
from [MyCube]
where [Date].[Year-Quarter-Month-Date].[Month].&[Feb-2004]
Approach 2: Such hierarchy doesn't exist
with set CurrentMonth as
[Date].[Month].currentmember
set DatesInCurrentMonth as
exists([Date].[Date].children, abc, "<<Any Measure group>>")
member measures.countofdaysinmonth as
count(DatesInCurrentMonth)
select measures.countofdaysinmonth on 0
from [MyCube]
where [Accident Date].[Month].&[Feb-2004]
Let me know if they work/have issues.

wrong result of parallelperiod() for DATE in MDX

I want to extract data for same period last year and last month.
for this i am using Parallelperiod(), for eg
PARALLELPERIOD([date].[year],1,[date].[date].[20-Sep-2014]) ,
for which I am getting output : 21-Sep-2014
and
PARALLELPERIOD([date].[month],1,[date].[date].[20-Sep-2014]) ,
for which I am getting output : 16-Aug-2014
Same function would throw some other date for some other month
Can you guide about the issue, where i am doing wrong or if there is some other alternative to this?
You must have some dates that do not exist in the cube.
What the PARALLELPERIOD function is doing is saying ok we are 262 members at the [date] level into 2014 - then it goes to 2013 and finds the member at the [date] level that is also 262 members in. Therefore unless you have complete sets of dates in your cube this function will return surprising results.
Therefore the solution is to ensure that all historical dates are represented in the cube. These extra dates should not cause any extra overhead as they will be creating empty space in the cube which is dealt with very well by SSAS

How can I create a calculated measure based on a filtered dimension?

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"