I am new to MDX and I am trying to apply date filter to year of date Hierarchy , i.e. I want count of all sales for each product number excluding NA, for date greater than 1/1/2016.
Write now I am using below query :
SELECT NON EMPTY { [Measures].[SALES COUNT] } ON COLUMNS
, NON EMPTY { ([PRODUCT CRIETERIA].[PRODUCT NUMBER].[PRODUCT NUMBER].ALLMEMBERS ) }
DIMENSION PROPERTIES MEMBER_CAPTION, MEMBER_UNIQUE_NAME ON ROWS
FROM
(
SELECT
( -{ [PRODUCT CRIETERIA].[PRODUCT NUMBER].&[NA] } ) ON COLUMNS
FROM
(
SELECT
(
{
[PRODUCT Creation Date].[PRODUCT Creation Date Hierarchy].[PRODUCT Creation Year].&[2016],
[PRODUCT Creation Date].[PRODUCT Creation Date Hierarchy].[PRODUCT Creation Year].&[2017]
}
)
ON COLUMNS FROM [Product_QA]))
WHERE ( [PRODUCT Creation Date].[PRODUCT Creation Date Hierarchy].CurrentMember )
CELL PROPERTIES VALUE, BACK_COLOR, FORE_COLOR, FORMATTED_VALUE, FORMAT_STRING, FONT_NAME, FONT_SIZE, FONT_FLAGS
But above query is working fine , but not right as I have to manually change this query each and every year.
I want result where date > 1/1/2016
How can I use greater than here to get desired result.
Thanks.
I found the solution - in general when using the Date dimension a colon range operator with a NULL on either side gives a range that is open on one side e.g. 2016 and above
[PRODUCT Creation Date].[PRODUCT Creation Date Hierarchy].[PRODUCT Creation Year].&[2016]
: NULL
upto and including 2016:
NULL:
[PRODUCT Creation Date].[PRODUCT Creation Date Hierarchy].[PRODUCT Creation Year].&[2016]
Related
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])
I’m hoping someone can help me out with restructuring/rewriting my MDX query – I’m fairly new to MDX and only know enough to be dangerous. I am using Mondrian if that makes a difference.
Here is the stacked bar chart I am producing…
Injuries by Month and Category
And here is my query (simplified to remove all the stuff not relevant to this question)…
WITH
SET [Date Range] AS {${mdxStartDateParam}.Parent : ${mdxEndDateParam}.Parent}
MEMBER [Measures].[Month Name] as [Incident Date.YQMD].currentmember.parent.parent.name || "-" || [Incident Date.YQMD].currentmember.name
SET [Classification Month Set] AS (
Hierarchize(
ORDER(
Hierarchize(FILTER([Classification].[Classification].members,[Classification].CURRENTMEMBER IN {Descendants([Classification].[${paramInjClass}])})),
[Measures].[Injury Count],
BDESC
)
) * [Date Range]
)
SELECT {[Measures].[Injury Count], [Measures].[Month Name]} ON COLUMNS,
NON EMPTY [Classification Month Set] ON ROWS
FROM [Injury Analysis]
The problem I have is that my two date parameters (${mdxStartDateParam} and ${mdxEndDateParam}) can be any date at the [Day] level, while my chart X Axis is showing at the [Month] level, and even if the ${mdxStartDateParam} is midway through a month my query is returning all data for the month.
eg. If I have an Injury that occurred on February 2nd but my ${mdxStartDateParam} is [Incident Date.YQMD].[2017].[Q1].[Feb].[17], then that Injuryis being included in the chart.
Is there a way I can restructure my MDX so that the bar for February does not show all data for February, but only the data for Fenruary that is >= ${mdxStartDateParam} and <= ${mdxEndDateParam}?
Since the Mondrian doesn't support sub-queries, you can't use your Calendar hierarchy for both where clause and axis. Also there is no way to filter days and show month only on axis. So, if you have two separate hierarchies for Days and Months, you may use the following:
WITH
SET [Date Range] AS [YourDateDim].[YourHierarchyNotInDateParam].[MonthLevel].Members
MEMBER [Measures].[Month Name] as [Incident Date.YQMD].currentmember.parent.parent.name || "-" || [Incident Date.YQMD].currentmember.name
SET [Classification Month Set] AS (
Hierarchize(
ORDER(
Hierarchize(FILTER([Classification].[Classification].members,[Classification].CURRENTMEMBER IN {Descendants([Classification].[${paramInjClass}])})),
[Measures].[Injury Count],
BDESC
)
) * [Date Range]
)
SELECT {[Measures].[Injury Count], [Measures].[Month Name]} ON COLUMNS,
NON EMPTY [Classification Month Set] ON ROWS
FROM [Injury Analysis]
WHERE {${mdxStartDateParam}:${mdxEndDateParam}})
Otherwise you have to deal with shown days and group them after.
Without knowing anything about the dialect of MDX you're using, or being able to see the dimension structure, my guess is that the problem is with the definition of [Date Range]:
SET [Date Range] AS {${mdxStartDateParam}.Parent : ${mdxEndDateParam}.Parent}
If the two parameters are at the Day level, does .Parent return their parent months?
The solution might be to make the date range be a set of days:
SET [Date Range] AS {${mdxStartDateParam} : ${mdxEndDateParam}}
and then aggregate by month somehow.
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
)
I am trying to retrieve month from parametrized date , by using :
vba!month(${parDate}) or
vba!datePart(m,${parDate}) or
vba!format(${parDate},'mmm')
None of the above is working.Can you guide, what is the right approach to do this?
(try uppercase 'MM' rather than 'mmm' - even 'mm' is wrong as it will look for minutes rather than months)
This question and answer looks at working with dates:
Changing a date format to a shorter date
MSDN is a good reference for the available vba functions in mdx that you can use to play around with dates. Current link is here:
http://msdn.microsoft.com/en-us/library/hh510163.aspx
I'm assuming you have a date dimension and would like to create a calculated measure that returns a numeric value that is the month.
Using AdWks I can do the following:
WITH
MEMBER [Measures].[DateValue] AS
[Date].[Calendar].CurrentMember.MemberValue
MEMBER [Measures].[DateKey] AS
[Date].[Calendar].CurrentMember.Member_Key
MEMBER [Measures].[DateMONTH] AS
Mid
(
[Measures].[DateKey]
,5
,2
)
SELECT
{
[Measures].[DateValue]
,[Measures].[DateKey]
,[Measures].[DateMONTH]
} ON 0
,Order
(
{
Exists
(
[Date].[Date].MEMBERS
,[Date].[Calendar Year].&[2010]
)
}
,[Date].[Calendar].CurrentMember.MemberValue
,BDESC
) ON 1
FROM [Adventure Works];
But maybe you'd just like to play around with today's date and extract the month:
WITH
MEMBER [Measures].[DateValue] AS
[Date].[Calendar].CurrentMember.MemberValue
MEMBER [Measures].[TodayKey] AS
format(Now(),'yyyMMdd')
MEMBER [Measures].[TodayMONTH] AS
Mid
(
[Measures].[TodayKey]
,5
,2
)
SELECT
{
[Measures].[DateValue]
,[Measures].[TodayKey]
,[Measures].[TodayMONTH]
} ON 0
,Order
(
{
Exists
(
[Date].[Date].MEMBERS
,[Date].[Calendar Year].&[2010]
)
}
,[Date].[Calendar].CurrentMember.MemberValue
,BDESC
) ON 1
FROM [Adventure Works];
I have a filter that selects a specific date in my date dimension, This will be passed in as a parameter into the MDX query.
Filter([Date Dimension].[Calendar Year Hierarchy].[Actual Date].members,
[Date Dimension].[Actual Date].CurrentMember.Properties( "Name" ) = '2011-09-01 00:00:00.000')
I would now like to select the weeks and/or months in the hierarchy above that.
[Date Dimension].[Calendar Year Hierarchy].[Month]
[Date Dimension].[Calendar Year Hierarchy].[Calendar Week]
I have tried several functions without much luck such as .Parent and DrillupLevel
I could be using them wrong or in the wrong spot,
thanks for the help
You could use the function GENERATE to get all ascendants:
Generate
(
{Filter([Date Dimension].[Calendar Year Hierarchy].[Actual Date].members,
[Date Dimension].[Actual Date].CurrentMember.Properties( "Name" ) =
'2011-09-01 00:00:00.000')},
{Ascendants([Date Dimension].[Calendar Year Hierarchy].CurrentMember)}
)
Query using Adventure Works:
Select
{[Measures].[Internet Sales Amount]} On Columns,
{Generate(
{Filter([Date].[Calendar].[Date].members,[Date].[Calendar].CurrentMember.Properties("Name") = 'April 1, 2004')},
{Ascendants([Date].[Calendar].CurrentMember)})} On Rows
From [Adventure Works]
If you know the level you're looking for you can use MDX Ancestor function instead of parent:
Ancestor([Date Dimension].[Calendar Year Hierarchy].currentmember,
[Date Dimension].[Calendar Year Hierarchy].[Month])
If no, it's fine using parent function. Note, using properties is not the quickest method to filter (for very large sets).
Why not using to StrToMember MDX function ?
StrToMember( ... here build your member with a string ... )
or if you can edit you mdx directly creating the statement directly with the help of a string builder ?
so the answer i have at the moment is
Filter([Date Dimension].[Calendar Year Hierarchy].[Actual
Date].members, [Date Dimension].[Actual
Date].CurrentMember.Properties( "Name" ) = '2011-09-01 00:00:00.000')
.item(0).parent
using the .item[0] to get the item in the set
and the .parent to get that items parent (in my case i am actually calling it 3 times)
if anyone has any better ideas would love to here them.
You can use STRTOSET and for each input parameter replace ] with ].Parent, this way you will have set of parents.