I want to create a member based on this problem
I have a Product A being sold
I want to find the largest range of consecutive days without sale
example:
days 1,2,3 the product not sale, after that,it sold for 15 consecutive days, at 19th day it didnt sell for 2 days and after that it sold every day until the end of the month
so my maximum days without sale was 3
The following query delivers in the Microsoft sample cube Adventure Works what you want:
WITH Member Measures.[days without sales] AS
IIf( [Measures].[Internet Sales Amount] > 0
, 0
,(Measures.[days without sales], [Date].[Calendar].CurrentMember.PrevMember) + 1
)
Member Measures.[Max days without sales] AS
Max( [Date].[Calendar].[Date].Members
,Measures.[days without sales]
)
SELECT { [Measures].[Max days without sales] }
ON COLUMNS
FROM [Adventure Works]
WHERE [Product].[Product].&[486]
The measure days without sales is defined recursively, and returns how many days up to and including the current member of the [Date].[Calendar] hierarchy there was no sales. You may need to adapt the criteria for "without sale", bearing in mind that in MDX, numerical comparisons treat NULL as 0 - which is different from SQL.
This measure only works correctly if there is a member in this hierarchy for each day, i. e. there are no gaps in this hierarchy. And actually, the definition is more general than just working for days: If you use months for the [Date].[Calendar].CurrentMember, it would give you the number of months without sales, etc. It works with each level of the hierarchy.
The measure Max days without sales does not contain the product in its definition, it delivers the maximum days for whatever is in context (in this case the product in the WHERE clause).
Please note that - as actually there is a loop over all days in the [Date].[Calendar] hierarchy when calculating Measures.[Max days without sales], and within that the recursion again iterates along the previous days, and all this for each cell in the result set - this may be slow for large reports.
Related
I want to calculate sales for promotion using it's date. I need 3 measures, avg sales from 21 days before promotion start date, sales in between of promotion's start and end date, and sales from 21 days after promotion's end date.
Why Visual Studio highlights avg in code below?
CREATE MEMBER CURRENTCUBE.[Measures].[Sales in promotion]
AS Avg(Existing([Promotion].[Promotion name].[Promotion name]),[Measures].[Sales]), ...
Same in here:
CREATE MEMBER CURRENTCUBE.[Measures].[Sales before promotion]
AS (EXISTING([Promotion].[Promotion name].[Promotion name]), AVG(strtomember("[Date].[Date].&["+ [Promotion].[Date].currentmember.member_key+"]").lag(21) : strtomember("[Date].[Date].&["+ [Promotion].[Date From].currentmember.member_key+"]"),
[Measures].[Sales])) ...
If I do sum(existing()) in first measure, the sum is calculated correctly, but it doesn't allow me to get average.
EXISTING will only help if [Promotion] is part of your query in either the WHERE or SELECT clause. If it is not included in either of these clause then EXISTING will be finding 1 member - the All member.
You could try NonEmpty and maybe move the period logic into a custom set?
WITH
SET [PERIOD] AS
STRTOSET(
"[Date].[Date].&["+ [Promotion].[Date].currentmember.member_key+"].lag(21)
:
[Date].[Date].&["+ [Promotion].[Date From].currentmember.member_key+"]"
)
From the code you posted I cannot tell if you want a daily average or and average per promotion ? Say there were 2 promotions over the 21 days does this mean you want (Total/2/21) ?
I've been tasked with a rather odd Time intelligence function by my finance group that I'm trying to puzzle out.
I've been asked with creating a measure within our SSAS Cube to allow for seeing previous quarter to date based on how far we are in the current quarter. But instead of seeing a standard idea of days elapsed currently versus days elapsed previously, they would like to see days remaining versus previous days remaining.
What I mean by that is, take 1/22/2015 for example. We have 48 days remaining in our current quarter, which I have by means of a calculated measure. I need to find the corresponding working day from the previous quarter where it is also at 48 days remaining.
At that point I could create a date range with some aggregate functions off of the first date in the previous quarter to the corresponding date found in the above and come up with what they are looking for.
The best idea I've had so far is to possibly do this in the database section itself, by creating a new column that is essentially the calculated number of days remaining but stored. But at that point I'm not sure how to take a calculated measure in SSAS and filter a previous quarter date member to use that property as it were.
Do you have an utility dimensions in your cube? We have one called TimeCalculations. In there we have things such as CurrentValue, MTDValue, PrevEquivMTD, Past7Days .... I think your new logic would fit in with such a dimension.
Here is an example of PrevEquivQTD against AdvWrks that I just had a play with. Guessing this doesn't really help your scenario but I had fun writing it:
WITH
SET [NonEmptyDates] AS
NonEmpty
(
[Date].[Calendar].[Date].MEMBERS
,[Measures].[Internet Sales Amount]
)
SET [LastNonEmptyDate] AS
Tail([NonEmptyDates])
SET [CurrQ] AS
Exists
(
[Date].[Calendar].[Calendar Quarter]
,[LastNonEmptyDate].Item(0)
)
MEMBER [Measures].[pos] AS
Rank
(
[LastNonEmptyDate].Item(0)
,Descendants
(
[CurrQ]
,[Date].[Calendar].[Date]
)
)
MEMBER [Measures].[PrevEquivalentQTD] AS
Sum
(
Head
(
Descendants
(
[CurrQ].ITEM(0).PrevMember
,[Date].[Calendar].[Date]
)
,[Measures].[pos]
)
,[Measures].[Internet Sales Amount]
)
SELECT
{[Measures].[pos],[Measures].[PrevEquivalentQTD]} ON 0
,[LastNonEmptyDate] ON 1
FROM
(
SELECT
[Date].[Calendar].[Date].&[20050111]
:
[Date].[Calendar].[Date].&[20080611] ON 0
FROM [Adventure Works]
);
Your Date is 1/22/2015. You want the Same Date in Previous Quarter which would be 8/22/2015.
If this is what you want, you will have to use MDX function ParallelPeriod as shown in sample below. Please replace it with your own Dimensions and Cube.
Select
ParallelPeriod
(
[Date].[Calendar Date].[Calendar Quarter], -- Level Expression
1, -- Index
[Date].[Calendar Date].[Date].&[20150122] -- Member Expression
) On 0
From [Adventure Works]
If you want the same date in the following quarter, then replace index 1 with -1.
Cheers
My MDX is fledgling at best, and it is a realistic possibility that I don't even know how to phrase my question correctly to search for an answer. Sorry if this is a duplicate.
I have a date/time hierarchy [Dates]:
[Work Date].[Dates].[Year].[Quarter].[Month].[Day]
What I want to do is return the previous 5 years worth of data, for the month of X (let's assume January):
Year Sub Total
2008 645712.11
2009 848075.43
2010 765802.60
However, I'm having trouble restricting the "Year" data, based on the specific month. I have tried this MDX code, but it yields no results at all:
SELECT [Measures].[Sub Total] ON 0,
[Work Date].[Dates].[Year] ON 1
FROM (
SELECT [Work Date].[Dates].[Month].&[01] ON 0
FROM [Data Warehouse])
If I edit the sub-select I can get a specific year, quarter and month... but I only want to restrict the month portion and not the year. I've looked into using an EXCEPT clause, but I run into the same issue. Does that make any sense? I appreciate any help, and am not opposed to reading long articles if it will further my learning / understanding. Thanks!
After your explanation in comments: To get the same child of each hierarchy level you can use the MDX function COUSIN (here the reference on msdn). As documentation said:
Returns the child member with the same relative position under a
parent member as the specified child member.
so in your case your Date dimension has to be complete without missing months or days, so you can write a query like this (I've tested on AdventureWorks)
with member [Measures].[Sub Total]
as (Cousin([Date].[Calendar].[Month].&[2004]&[1], [Date].[Calendar].CurrentMember), [Measures].[Internet Sales Amount]) , Format_string = 'Currency'
Select {[Measures].[Internet Sales Amount],[Measures].[Sub Total] } on 0
,{
[Date].[Calendar].[Calendar Year].&[2002]
,[Date].[Calendar].[Calendar Year].&[2003]
,[Date].[Calendar].[Calendar Year].&[2004]
} on 1
from [Adventure Works]
I've put side by side the total and the sub total for the years. I am considering only these 3 years because they are complete from jan to dec and I can apply cousin operator without problem.
Hope this help!
I want to create a barchart with a bar for each month and some measure.
But i also want to filter on a range of day which might not completly overlap some of the month.
When that happen I would like the aggregate count for those month to only aggregat over the days that fall in my date range not get the aggregate for the whole month.
Is that possible with MDX and if it is how should the request look like?
Create a second time dimension, using a virtual dimension of the original dimension. Use one dimension in the WHERE and another in the SELECT.
This often happens anyway if some people want 'Business Time' of quarters and periods, and others prefer months. Or if you have a financial year which runs April-April.
You can use subselect. You can find more information on this page and this page:
When a member is specified in the axis clause then that member with
its ascendants and descendants are included in the sub cube space for
the subselect; all non mentioned sibling members, in the axis or
slicer clause, and their descendants are filtered from the subspace.
This way, the space of the outer select has been limited to the
existing members in the axis clause or slicer clause, with their
ascendants and descendants as mentioned before.
Here is an example:
SELECT { [Customer].[Customer Geography].[Country].&[Australia]
, [Customer].[Customer Geography].[Country].&[United States]
} ON 1
, {[Measures].[Internet Sales Amount], [Measures].[Reseller Sales Amount]} ON 0
FROM ( SELECT {[Customer].[Customer Geography].[Country].&[Australia]
, [Customer].[State-Province].&[WA]&[US]} ON 0
FROM [Adventure Works]
)
The result will contain one row for Autralia and another one for the United States. With the subselect, I restricted the value of United Stated to the Washington state.
One way I found to do it with Mondrian is as follow
WITH MEMBER [Measures].[Units Shipped2] AS
SUM
(
{
exists([Store].[Store Country].currentmember.children,{[Store].[USA].[WA],[Store].[USA].[OR]})
},[Measures].[Units Shipped]
)
MEMBER [Measures].[Warehouse Sales2] AS
SUM
(
{
exists([Store].[Store Country].currentmember.children,{[Store].[USA].[WA],[Store].[USA].[OR]})
},[Measures].[Warehouse Sales]
)
SELECT
{[Measures].[Units Shipped2],[Measures].[Warehouse Sales2]} ON 0,
NON EMPTY [Store].[Store Country].Members on 1
FROM [Warehouse]
I am not sure if the filtering will be done in SQL like below and give good performance or be run locally
select Country, sum(unit_shipped)
where state in ('WA','OR' )
group by Country
I have a requirement to show a report which calculates the average selling unit price of each product and then multiplies this average by the number of units forecasted to sell in the next year (for each product).
At this point my main issue is getting this set up so the totals roll up correctly when viewing at product category level. Using AdventureWorks as an example (and sales orders instead of forecasts) I've got this far...
with
member [Measures].[Sales Order Value]
as sum(descendants([Product].[Product Categories].currentMember,
[Product].[Product Categories].[Product]),
[Measures].[Average Unit Price] * [Measures].[Order Count]),
format_string = "Currency"
select ([Date].[Calendar].[Calendar Year].&[2008],
{[Measures].[Sales Order Value] }) on columns,
[Product].[Product Categories].[Subcategory].members on rows
from [Adventure Works]
I think this is about right, I believe this is going down to product level to apply the calculation between product average unit price and any sales orders for the product.
My issue is that I think the average unit price is being calculated over all data, I need to alter this to pick up an average based on the last 12 months only.