MDX sum from date dim to now - mdx

I am trying to create a calculated measure showing the SUM of a measure over a period of time FROM a current member of a date dimension TO now.
The following code is pretty bad but I hope it will give you an idea:
With Member [Measures].[NumberFromDate] as (
sum(
[Date].currentMember:STRTOMEMBER(Format(Now() , '[Date]\.&[yyyy-mm-dd hh:mm:ss.0]' )
), [Measures].[Number]
)
In my schema Date is a Dimension with a single Level Date of type Date.
This mdx code give me an error "Cannot find MDX member '[Date]'".

Try strToSet instead:
With Member [Measures].[NumberFromDate] as (
sum(
strToSet(
'[Date].currentMember:[Date].[' & Format(Now() ,'yyyy-mm-dd hh:mm:ss.0') & ']'
)
)
, [Measures].[Number]
)
Here is a very similar request on MSDN:
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/fdee9f45-8383-4446-b022-e9e877477aec/mdx-date-format
I'm a bit unsure if your format sring is ok. Is this really the string used in your cube?
'yyyy-mm-dd hh:mm:ss.0'

Related

MDX Dynamic dimension filter based on value of other dimension

How can I filter using values from two dimension in MDX?
The required result should include records where [Purchase Date].[Date] is before today minus number of years from [Accounting Date].[Year]. So, the result should include YoY records from today based on [Purchase Date].[Date] for each [Accounting Date].[Year] member.
I would like something like the following:
SELECT NON EMPTY [Measures].[Amount] ON 0,
NON EMPTY [Accounting Date].[Year].[Year].ALLMEMBERS ON 1
FROM [Tabular_Model]
WHERE (
NULL :
STRTOMEMBER("[Purchase Date].[Date].&["+ Format(DateAdd("YYYY", [Accounting Date].[Year].CURRENTMEMBER.MEMBER_VALUE - 2020, Now()),"yyyy-MM-ddT00:00:00") + "]")
)
But it fails with error: Execution of the managed stored procedure DateAdd failed with the following error: Microsoft::AnalysisServices::AdomdServer::AdomdException.
The syntax for 'All' is incorrect. (All).
Why CURRENTMEMBER.MEMBER_VALUE works for HAVING but not in my WHERE clause? What is the right way?
Try the following measure and query:
WITH
MEMBER [Measures].[Trailing Amount] as SUM({NULL :
STRTOMEMBER("[Purchase Date].[Date].&["+ Format(DateAdd("YYYY", [Accounting Date].[Year].CURRENTMEMBER.MEMBER_VALUE - 2020, Now()),"yyyy-MM-ddT00:00:00") + "]")}, [Measures].[Amount])
SELECT [Measures].[Trailing Amount] ON 0,
NON EMPTY [Accounting Date].[Year].[Year].MEMBERS ON 1
FROM [Tabular_Model]
If MDX doesn't perform as well as you hope, then you might consider adding the following DAX measure into your Tabular model. The following DAX query illustrates how to use it, but if you put this DAX measure into your model, you can query it with MDX queries and it should likely perform better than an MDX calculation:
define
measure 'Your Table Name Here'[Trailing Sales] =
VAR YearOffset = SELECTEDVALUE('Accounting Date'[Year]) - 2020
VAR NowDate = NOW()
VAR EndDate = DATE(YEAR(NowDate)+YearOffset,MONTH(NowDate),DAY(NowDate))
RETURN CALCULATE([Amount], 'Purchase Date'[Date] <= EndDate)
evaluate ADDCOLUMNS(ALL('Accounting Date'[Year]),"Trailing Sales",[Trailing Sales])

Get schedules of particular date from date ranges with MDX query

I already posted this problem many times, but unfortunately nobody could understand, I m sorry for my poor english :(
I reformulate ...
I have following fact table
I want to get records that match with a particular date and day of week (JOUR) in all dates range (DATE_DEB, DATE_FIN)
I can do that in SQL like this:
SELECT DATE_DEB,
DATE_FIN,
ID_HOR,
to_char(HR_DEB,'hh24:mi:ss') as HR_DEB,
to_char(HR_FIN,'hh24:mi:ss') as HR_FIN,
JOUR
FROM GRP_HOR HOR, GRP
WHERE GRP.ID_ACTIV_GRP = HOR.ID_ACTIV_GRP
AND TO_DATE('1998-01-08', 'YYYY-MM-DD') between DATE_DEB and DATE_FIN
AND 1 + TRUNC(TO_DATE('1998-01-08', 'YYYY-MM-DD')) - TRUNC(TO_DATE('1998-01-08', 'YYYY-MM-DD'), 'IW') = JOUR
So, I'll get 29 records (see below) which included in each range and match with the day of week (JOUR ), after that I want to enlarge them by hours (HR_DEB, HR_FIN).
The problem is, what's how the best way to do this ?
Create 2 date dimension and link them with DATE_DEB, DATE_FIN.
Create 2 Time dimension and link them with HR_DEB, HR_FIN.
How can I implement the between SQL clause in MDX ? Or geater than or Less than ?
Thank you in advance.
OUTPUT :
To specify a range of dates in MDX you just use the colon operator :
Here is the documentation on MSDN: https://learn.microsoft.com/en-us/sql/mdx/range-mdx?view=sql-server-2017
This is the example they give:
With Member [Measures].[Freight Per Customer] as
(
[Measures].[Internet Freight Cost]
/
[Measures].[Customer Count]
)
SELECT
{[Ship Date].[Calendar].[Month].&[2004]&[1] : [Ship Date].[Calendar].[Month].&[2004]&[3]} ON 0,
[Product].[Category].[Category].Members ON 1
FROM
[Adventure Works]
WHERE
([Measures].[Freight Per Customer])

Next available Date

I have a tubular model that has a standard star schema
On my dim date table there is a column that flags UK holidays
I would like to not included this date if a key chooses a date that has been flagged but the next availble date
I don't have much access to the database to build a function for this as Ive seen others do
Could anyone suggest some Dax or a method of doing this
Thanks so much in advance
sample
You can create a calculated column to get the next working dateKey if date is flagged as non working date. In case date is not flagged the column contains the dateKey value.
Use this DAX expression in the calculated column:
=
IF (
[isDefaultCalendarNonWorkingDay] = 1,
CALCULATE (
MIN ( [dateKey] ),
FILTER (
DimDate,
[dateKey] > EARLIER ( [dateKey] )
&& [isDefaultCalendarNonWorkingDay] = 0
)
),
[dateKey]
)
I've recreated you DimDate table with some sample data:
Let me know if this helps.

Active Account count on specific date in MDX

I have a situation where I need to get active account count on a specific date.
I have start date end date in SQL it looks like
select count(account) where start_date <=#date and end_date >=#date
In MDX, I tried below one
AGGREGATE(
{
NULL:LINKMEMBER
(
[DATE].[YQMWD].CURRENTMEMBER
, [StartDate].[YQMWD]
)
}
*
{
LINKMEMBER
(
[DATE].[YQMWD].CURRENTMEMBER
, [EndDate].[YQMWD]
):NULL
}
, ([Measures].[AccountCount])
)
This Code is returning me perfect on date level only but once I am traversing to Week or Month it is considering the whole month of the active value. But during the selected month period many account getting deactivate.
If anybody faced this kind of measure before like
"Active value on specific date" .
I thought about the following but then noticed that you are dealing with two distinct dimensions [StartDate] and [EndDate] so using the range operator : is incorrect:
AGGREGATE(
UNION(
{
NULL
:
LINKMEMBER(
[DATE].[YQMWD].CURRENTMEMBER
, [StartDate].[YQMWD]
)
}
,{
LINKMEMBER(
[DATE].[YQMWD].CURRENTMEMBER
, [EndDate].[YQMWD]
)
:
NULL
}
)
, ([Measures].[AccountCount])
)
If we look in the definition of LINKMEMBER then it says the following:
https://msdn.microsoft.com/en-us/library/ms146058.aspx
The LinkMember function returns the member from the specified
hierarchy that matches the key values at each level of the specified
member in a related hierarchy. Attributes at each level must have the
same key cardinality and data type. In unnatural hierarchies, if there
is more than one match for an attribute's key value, the result will
be an error or indeterminate.
So it makes sense the behaviour you are encountering - if [DATE].[YQMWD].CURRENTMEMBER is a week, then the key of this member is not going to map across to either [StartDate].[YQMWD] or [EndDate].[YQMWD].
Moreover if a week is selected then how do you interpret this sql logic where start_date <=#date and end_date >=#date as a week is made up of 7 days so #date has 7 possibilities?
Maybe you could use EXISTS function inside the LINKMEMBER function so that only Date level members are used. Then we have this problem that Exists will return a set type but the first arg of LINKMEMBER needs to be of type member. So get hold of the first and last members using Tail and Head like so:
AGGREGATE(
{
NULL
:
LINKMEMBER(
HEAD(
EXISTS(
[DATE].[YQMWD].CURRENTMEMBER
,[DATE].[YQMWD].[Date] ////<<if CURRENTMEMBER is a week then Exists will return a set of 7 Date members
)
,1 ////<<if CURRENTMEMBER is a week then Head(..1) will return a set of 1 Date member - the first date in the week
).ITEM(0).ITEM(0) ////<<this converts from single member set to a member
, [StartDate].[YQMWD]
)
}
*
{
LINKMEMBER(
TAIL(
EXISTS(
[DATE].[YQMWD].CURRENTMEMBER
,[DATE].[YQMWD].[Date]
)
,1
).ITEM(0).ITEM(0)
, [EndDate].[YQMWD]
)
:NULL
}
, ([Measures].[AccountCount])
)
How about first checking for the type of input and then giving results? In this case CoalesceEmpty will check that and return the results. Used FirstChild function to fetch the first date always from the range.
CoalesceEmpty
(
AGGREGATE
(
{NULL:LINKMEMBER([DATE].[YQMWD].CURRENTMEMBER.FIRSTCHILD.FIRSTCHILD.FIRSTCHILD.FIRSTCHILD, [StartDate].[YQMWD])}
*
{LINKMEMBER([DATE].[YQMWD].CURRENTMEMBER.FIRSTCHILD.FIRSTCHILD.FIRSTCHILD.FIRSTCHILD, [EndDate].[YQMWD]):NULL}
, ([Measures].[AccountCount])
)//--If it is a year
,
AGGREGATE
(
{NULL:LINKMEMBER([DATE].[YQMWD].CURRENTMEMBER.FIRSTCHILD.FIRSTCHILD.FIRSTCHILD, [StartDate].[YQMWD])}
*
{LINKMEMBER([DATE].[YQMWD].CURRENTMEMBER.FIRSTCHILD.FIRSTCHILD.FIRSTCHILD, [EndDate].[YQMWD]):NULL}
, ([Measures].[AccountCount])
)//--If it is a quarter
,
AGGREGATE
(
{NULL:LINKMEMBER([DATE].[YQMWD].CURRENTMEMBER.FIRSTCHILD.FIRSTCHILD, [StartDate].[YQMWD])}
*
{LINKMEMBER([DATE].[YQMWD].CURRENTMEMBER.FIRSTCHILD.FIRSTCHILD, [EndDate].[YQMWD]):NULL}
, ([Measures].[AccountCount])
)//--If it is a month
,
AGGREGATE
(
{NULL:LINKMEMBER([DATE].[YQMWD].CURRENTMEMBER.FIRSTCHILD, [StartDate].[YQMWD])}
*
{LINKMEMBER([DATE].[YQMWD].CURRENTMEMBER.FIRSTCHILD, [EndDate].[YQMWD]):NULL}
, ([Measures].[AccountCount])
)//--If it is a week
,
AGGREGATE
(
{NULL:LINKMEMBER([DATE].[YQMWD].CURRENTMEMBER, [StartDate].[YQMWD])}
*
{LINKMEMBER([DATE].[YQMWD].CURRENTMEMBER, [EndDate].[YQMWD]):NULL}
, ([Measures].[AccountCount])
)//--If it is a date
)

IIF in With Member comparing dates

I am very new to MDX and have a basic question. I would like a calculated measure which returns one value for dates less than a specified date, and another value if greater than a specified date. I have attempted:
with member [measures].[tempmeasure] as
IIF
(
[Date].[Date].CurrentMember < [Date].[Date].&[20100501]
, 1
, 2
)
select
[Date].[Date].Members
*
[measures].[tempmeasure] on columns
from [MyCube]
And this does not seem to work. That is using MS SSAS 2008.
Any ideas what I could be doing wrong?
With:
IIF([Date].[Date].CurrentMember < [Date].[Date].&[20100501], 1, 2)
you're comparing two tuple values and not the date members themselves.
You can have a look here for a tutorial on tuples, sets, etc...
As you're using AS, I think you can use the DataDiff function to compute the number of days between your two dates:
DateDiff("d", [Date].[Date].CurrentMember.MemberValue, [Date].[Date].&[20100501].MemberValue )
Otherwise, you may have some member properties available for that purpose:
IIF([Date].[Date].CurrentMember.Properties( 'prop-name', TYPED ) < [Date].[Date].&[20100501].Properties( 'prop-name', TYPED ) , 1, 2)
Cheers.
Please use below expression
IIF
(
[Date].[Date].Currentmember.MemberValue <
[Date].[Date].&[20100501].MemberValue
, 1
, 2
)
I have tested it is working as expected.....
Please let me know if you have any questions
IIF expects a logical expression which returns a boolean value. I think in your case
[Date].[Date].CurrentMember will return a dimension value, a set. Less than operator in this case will cause a syntax error.