MDX for Zero months in last 12 = Number of zero transacting months in the last 12 months rolling window - mdx

I am working on MDx query to count the number ZERO txn for each product for last 12 months from today's date. Prepared MDX query for Adventure works fine but my 2nd query running on my Acutal cube working correctly.
Can you please help me out to rectify the query or any filter needed to get correct results like 1st sample query?
1st Sample Query on Adventure Works: (working correctly)
WITH Member [Measures].[Months With Zero Sales] AS
COUNT(
FILTER(
DESCENDANTS(
{[Date].[Calendar].[Month].&[2008]&[1].LAG(12):[Date].[Calendar].[Month].&[2008]&[1]}, [Date].[Calendar].[Month]) ,
[Measures].[Sales Amount] = 0 ) )
SELECT {[Measures].[Months With Zero Sales]} ON 0,
[Product].[Product Model Lines].[Product Line].Members on 1
FROM [Adventure Works];
Product Lines Months With Zero Sales]
----------- -----------------
Accessory 0
Componenets 0
Mountain 0
Road 0
Touring 6
2nd Query on my Cube:
WITH Member [Measures].[Zero Months in last 12] AS
COUNT(
FILTER(
DESCENDANTS(
{[Settlement Date].[Calendar].[Settlement Calendar Month].&[2014]&[1].LAG(12):
[Settlement Date].[Calendar].[Settlement Calendar Month].&[2014]&[1]},
[Settlement Date].[Calendar].[Settlement Calendar Month]),
[Measures].[Transaction Count] = 0 ) )
SELECT {[Measures].[Transaction Count] ,[Measures].[Zero Months in last 12]} ON 0,
[Terminal].[terminal ID].members on 1
FROM [cubetxn]
I'm expecting if non zero where "transaction count" is (null), even if there is transaction count not null, there could be chances to have one month with empty tuples.
Can you please correct my query or someone can give me sample query which should able to give me total zero month txn count for last 12 month of each product.
Terminal ID Transaction Count Zero Months in last 12
---------- ----------------- -------------------------
All Terminals 504,112,053 0
Q1001 138,832 0
Q1002 (null) 0
Q1003 88,800 0
Q1004 (null) 0

First comment is that this is a quicker pattern to use when doing a count/filter:
WITH
MEMBER [Measures].[Months With Zero Sales] AS
Sum
(
Descendants
(
{
[Date].[Calendar].[Month].&[2008]&[1].Lag(12)
:
[Date].[Calendar].[Month].&[2008]&[1]
}
,[Date].[Calendar].[Month]
)
,IIF
(
[Measures].[Sales Amount] = 0
,1
,null
)
)
SELECT
{[Measures].[Months With Zero Sales]} ON 0
,[Product].[Product Model Lines].[Product Line].MEMBERS ON 1
FROM [Adventure Works];
Based on this more efficient approach does the following work?
WITH
MEMBER [Measures].[Zero Months in last 12] AS
Sum
(
Descendants
(
{
[Settlement Date].[Calendar].[Settlement Calendar Month].&[2014]&[1].Lag(12)
:
[Settlement Date].[Calendar].[Settlement Calendar Month].&[2014]&[1]
}
,[Settlement Date].[Calendar].[Settlement Calendar Month]
)
,IIF
(
[Measures].[Transaction Count] = 0
,1
,0
)
)
SELECT
{
[Measures].[Transaction Count]
,[Measures].[Zero Months in last 12]
} ON 0
,[Terminal].[terminal ID].MEMBERS ON 1
FROM [cubetxn];
If there is still a problem then why not reconstruct your script so you can manually check what to expect. So for the AdvWrks script I'd run this so that I could actually confirm that the 6 is correct:
SELECT
{[Measures].[Sales Amount]} ON 0
,
Descendants
(
{
[Date].[Calendar].[Month].&[2008]&[1].Lag(12)
:
[Date].[Calendar].[Month].&[2008]&[1]
}
,[Date].[Calendar].[Month]
)
*
[Product].[Product Model Lines].[Product Line].MEMBERS ON 1
FROM [Adventure Works];
So against your cube what does the following return?
SELECT
{[Measures].[Transaction Count]} ON 0
,
Descendants
(
{
[Settlement Date].[Calendar].[Settlement Calendar Month].&[2014]&[1].Lag(12)
:
[Settlement Date].[Calendar].[Settlement Calendar Month].&[2014]&[1]
}
,[Settlement Date].[Calendar].[Settlement Calendar Month]
)
*
[Terminal].[terminal ID].MEMBERS ON 1
FROM [cubetxn];

//Total Transactions count Weekend Sunday (i’ve date dimesion which holds day_in_week=’Sun’ for respective dates)
WITH SET AllTranSundays as
EXISTS(DATE.DATE.DATE.MEMBERS, DATE.DATE.day_in_week.&[Sun], "Sales")
//Count of all sundays which had transactions.
MEMBER Measures.CntAllTranSundays AS
COUNT(AllTranSundays)
//YTD Days = Count of days within calendar year to date
MEMBER Measures.CntDaysYTD as
COUNT(DESCENDANTS(ANCESTOR([DATE].[date].CURRENTMEMBER,
3), 3).item(0).item(0)
: [DATE].[date].CURRENTMEMBER)
//YTD Transactions = Transaction count year to date
MEMBER Measures.CntTranYTD as
COUNT(
EXISTS(
{DESCENDANTS(ANCESTOR([DATE].[date].CURRENTMEMBER,
3), 3).item(0).item(0)
: [DATE].[date].CURRENTMEMBER}, , "Sales"
)
//Zero months in last 12 = Number of zero transacting months in the last 12 months rolling window
MEMBER Measures.CntZeroTransactingMonths as
COUNT(
{ANCESTOR([DATE].[date].CURRENTMEMBER, 1).ITEM(0).LAG(12) : ANCESTOR([DATE].[date].CURRENTMEMBER, 1).ITEM(0)}
-
EXISTS({ANCESTOR([DATE].[date].CURRENTMEMBER, 1).ITEM(0).LAG(12) : ANCESTOR([DATE].[date].CURRENTMEMBER, 1).ITEM(0)}
, ,
"Sales")
)
//Consecutive zero months = Number of consecutive zero transacting months in last 12 months rolling window
Question Do you want a count of instances when consecutive months had zero transactions.
Or do you want a count of number of months which had consecutively no transactions?
What I am trying to say is say Jan, March, June, July, August, October, November had no transactions in the rolling last 12 months
As per case 1: the answer should be 2
As per case 2: the answer should be 5.
Will update my answer as per your clarification.
SELECT
{Measures.CntAllTranSundays, Measures.CntDaysYTD, Measures.CntTranYTD, Measures.CntZeroTransactingMonths} ON 0
FROM [YourCube]
where
[date].[date].[date].&[02/28/2015]

Related

How to get last years qty in measure

How can I create a measure that has previous years Qty SHipped by month that will be used against a Current year measure showing a variance?
I want to take last years qty shipped minus the Plan(I already have this measure working) to get a variance. I have a dimension called dates that has a YY.
example calc..
[Measure].[pyqty] - [Measure].[Plan]
Thanks.
May help you something like this:
It calculates the QTD of the parallel previous period
WITH MEMBER [Measures].[Current QTD] AS
Sum
(
QTD([Date].[Calendar].CurrentMember)
,[Measures].[Internet Order Quantity]
)
MEMBER [Measures].[Last QTD] AS
Sum
(
YTD
(
ParallelPeriod
(
[Date].[Calendar].[Calendar Quarter]
,1
,[Date].[Calendar].CurrentMember
)
)
,[Measures].[Internet Order Quantity]
)
select {[Measures].[Current QTD],[Measures].[Last QTD]} ON 0
FROM [Adventure Works]
WHERE [Date].[Calendar].[Month].&[2005]&[11]
Take a o look at Time Calculations, in order to add time intelligence to your cube

MDX Running total on every date member

I use the following MDX calculation to get the stock value per day:
SUM({NULL:[Date].[Calendar Hierarchy].CURRENTMEMBER} * [Measures].[Qty])
However this is giving me the following result
Date QtyOnHand
1/1/2015 10
4/1/2015 15
5/1/2015 16
Mark that the dates 2/1/2015 and 3/1/2015 are not shown, because there are no transactions on them.
I would like to get these shown to get the following result:
Date QtyOnHand
1/1/2015 10
2/1/2015 10
3/1/2015 10
4/1/2015 15
5/1/2015 16
How can I adjust my MDX statement to this?
Does IsEmpty help?
SUM(
{NULL:[Date].[Calendar Hierarchy].CURRENTMEMBER}
* IIF(
IsEmpty([Measures].[Qty])
,0
,[Measures].[Qty]
)
)
If it helps then it won't help performance.
I've tested the above and unsure why you do the cross-join inside the Sum - more standard is just to use the second argument.
This AdvWrks script is an example of your scenario i.e. there are gaps in the data:
SELECT
{[Measures].[Internet Sales Amount]} ON 0
,{
[Date].[Calendar].[Date].&[20050801]
:
[Date].[Calendar].[Date].&[20051201]
} ON 1
FROM [Adventure Works];
Here is the query using IsEmpty (with IIF):
WITH
MEMBER [Measures].[roll] AS
Sum
(
{[Date].[Calendar].[Date].&[20050801] : [Date].[Calendar].CurrentMember}
,IIF
(
IsEmpty([Measures].[Internet Sales Amount])
,0
,[Measures].[Internet Sales Amount]
)
)
SELECT
{[Measures].[Internet Sales Amount],[Measures].[roll]} ON 0
,{
[Date].[Calendar].[Date].&[20050801]
:
[Date].[Calendar].[Date].&[20051201]
} ON 1
FROM [Adventure Works];
Some of the results are the following:
So in your scenario I think this is very similar:
SUM(
{NULL:[Date].[Calendar Hierarchy].CURRENTMEMBER}
, IIF(
IsEmpty([Measures].[Qty])
,0
,[Measures].[Qty]
)
)

Count Working Days MDX

I would like to count the working days of a spesific time range and then find the Average Daily Dispatches.Currently the time range is at WHERE statement.
I believe that I have include the date range in the 1st Member but I can't figure how to count the dates in a month range.
Any suggestments?
WITH MEMBER [Measures].[Working Days] AS
COUNT(Date.[Working Date].&[1])--Doesn't work
MEMBER [Measures].[Average Daily Dispatches] AS
[Measures].[Total Dispatches]/[Measures].[Working Days]
SELECT [Measures].[Average Daily Dispatches] ON 0
FROM [cube]
WHERE (
[Date].[Month].&[2015-01-01T00:00:00]:[Date].[Month].&[2015-08-01T00:00:00]
);
Use the NonEmpty function to yield those working dates on which there was a dispatch. Then use COUNT on top of this.
WITH MEMBER [Measures].[Working Days] AS
COUNT
(
NonEmpty
(
[Date].[Working Date].MEMBERS,
[Measures].[Total Dispatches]
)
)
Some sort of alternative seems to exist using Exists/Existing (I think 1 is Monday in the AdvWrks cube!)
WITH
MEMBER [Measures].[MondayCnt] AS
Count
(
Exists
(
(EXISTING
[Date].[Calendar].MEMBERS)
,[Date].[Day of Week].[1]
)
)
MEMBER [Measures].[Averge] AS
[Measures].[Internet Sales Amount] / [Measures].[MondayCnt]
SELECT
{
[Measures].[Internet Sales Amount]
,[Measures].[MondayCnt]
,[Measures].[Averge]
} ON 0
,
[Date].[Calendar].[Month].&[2006]&[6]
:
[Date].[Calendar].[Month].&[2007]&[6] ON 1
FROM [Adventure Works];
The above results in the following:

Create Set to get Last month of Each Year

I would like to create a set that returned the last Date for each year. For example all previous years would return December, but the current year would only return the current month.
WITH
SET testset AS
NonEmpty
(
Generate
(
{
OpeningPeriod([Date].[Calendar].[Month])
:
ClosingPeriod([Date].[Calendar].Month)
}
,{[Date].[calendar].CurrentMember}
)
,[Measures].[Sale Amount]
)
SELECT
NON EMPTY
(
[Measures].[Sale Amount]
,[Date].[Year].[Year]
) ON 0
,NON EMPTY
[testset] ON 1
FROM [Cube]
Here is an example of a script that returns the values for each month. I've tried using tail and lastchild, but that only returns the most recent. I would like it to return for every Year.
In terms of just the last month - ignoring whether there is data for it or not the following:
WITH
SET [AllYears] AS
[Date].[Calendar].[Calendar Year].MEMBERS
SET [LastMths] AS
Generate
(
[AllYears] AS S
,Tail
(
Descendants
(
S.CurrentMember
,[Date].[Calendar].[Month]
)
,1
)
)
SELECT
{} ON 0
,[LastMths] ON 1
FROM [Adventure Works];
Returns this:
If I want to adapt the above so that it is the last month per year that has data for a specific measure then wrap NonEmpty around the set created by Descendants:
WITH
SET [AllYears] AS
[Date].[Calendar].[Calendar Year].MEMBERS
SET [LastMths] AS
Generate
(
[AllYears] AS S
,Tail
(
NonEmpty //<<new
(
Descendants
(
S.CurrentMember
,[Date].[Calendar].[Month]
)
,[Measures].[Internet Sales Amount] //<<new
)
,1
)
)
SELECT
{} ON 0
,[LastMths] ON 1
FROM [Adventure Works];
It now gives us this:
We can then add in the tuple you have on rows (I have used the attribute hierarchy this time for years as [Date].[Calendar] is already in use)
WITH
SET [AllYears] AS
[Date].[Calendar].[Calendar Year].MEMBERS
SET [LastMths] AS
Generate
(
[AllYears] AS S
,Tail
(
NonEmpty
(
Descendants
(
S.CurrentMember
,[Date].[Calendar].[Month]
)
,[Measures].[Internet Sales Amount]
)
,1
)
)
SELECT
NON EMPTY
(
[Measures].[Internet Sales Amount]
,[Date].[Calendar Year].[Calendar Year]
) ON 0
,[LastMths] ON 1
FROM [Adventure Works];
Now we get this:
#Whytheq has already given a very good solution. Treat this as an alternative. This might be a tad faster as it doesn't use the GENERATE function (not sure though!).
Have a calculated/cube measure which basically tells whether a month is the last month of the year. Then select those months out of the set of months.
with member measures.islastchild as
iif
(
[Date].[Calendar].currentmember is
[Date].[Calendar].currentmember.parent.parent.parent.lastchild.lastchild.lastchild,
1,
null
)
The member measures.islastchild returns 1 if the month is the last month of the year. Else it would return null.
set lastmonths as
filter(
[Date].[Calendar].[Month].members,
measures.islastchild = 1
)
The set lastmonths is then the set you need.
edit
To further improve the performance, you can NonEmpty function instead of the iterative FILTER function.
set lastmonths as
NonEmpty(
[Date].[Calendar].[Month].members,
measures.islastchild
)
select lastmonths on 1,
{} on 0
from [Adventure Works]
EDIT 2: To get the last non month with sales
with member measures.islastnonemptychild as
iif
(
[Date].[Calendar].currentmember is
TAIL(NonEmpty([Date].[Calendar].currentmember.parent.parent.parent.lastchild.lastchild.children, [Measures].[Sale Amount])).ITEM(0),
1,
null
)
set nonemptylastmonths as
NonEmpty(
[Date].[Calendar].[Month].members,
measures.islastnonemptychild
)

MDX Count over time (years - not within a year)

I'd like to be able to rollup the count of commitments to a product over years -
The data for new commitments in each year looks like this:
Year | Count of new commitments | (What I'd like - count of new commitments to date)
1986 4 4
1987 22 26
1988 14 40
1989 1 41
I know that within a year you can do year to date, month to date etc, but I need to do it over multiple years.
the mdx that gives me the first 2 columns is (really simple - but I don't know where to go from here):
select [Measures].[Commitment Count] on 0
, [Date Dim].[CY Hierarchy].[Calendar Year] on 1
from [Cube]
Any help would be great
In MDX something along the line:
with member [x] as sum(
[Date Dim].[CY Hierarchy].[Calendar Year].members(0) : [Date Dim].[CY Hierarchy].currentMember,
[Measures].[Commitment Count]
)
select [x] on 0, [Date Dim].[CY Hierarchy].[Calendar Year] on 1 from [Cube]
Use a common table expression:
with sums (year,sumThisYear,cumulativeSum)
as (
select year
, sum(commitments) as sumThisYear
, sum(commitments) as cumulativeSum
from theTable
where year = (select min(year) from theTable)
group by year
union all
select child.year
, sum(child.commitments) as sumThisYear
, sum(child.commitments) + parent.cumulativeSum as cumulativeSum
from sums par
JOIN thetable Child on par.year = child.year - 1
group by child.year,parent.cumulativeSum
)
select * from sums
There's a bit of a "trick" in there grouping on parent.cumulativeSum. We know that this will be the same value for all rows, and we need to add it to sum(child.commitments), so we group on it so SQL Server will let us refer to it. That can probably be cleaned up to remove what might be called a "smell", but it will work.
Warning: 11:15pm where I am, written off the top of my head, may need a tweak or two.
EDIT: forgot the group by in the anchor clause, added that in