I'm trying to add a calculated member to my cube, which will return the first fiscal year where there is any data at all in a particular measure.
The purpose is to suppress (i.e. NULLify) various year-on-year calculated measures when the year is this first year: in that year, comparison with the previous year is meaningless.
I've got this so far:
WITH MEMBER Measures.DataStartYear_Sales
AS
HEAD(
NONEMPTY([Calendar].[Fiscal Periods].[Fiscal Year].Members,[Measures].[QuantityOrdered])
,1).Item(0).Properties("NAME")
At the moment:
a. It's a query-scoped measure, as that's easier to experiment with.
b. It returns the first year's Name, as that's easier to see. Eventually I'll just return the member itself, and do an IS comparison against the year hierarchy .CurrentMember in the other calculated member calculations.
The problem I expected, which has happened, is that I only want this measure to be calculated once, over the whole cube. But when I used it in a query, it obviously reacts to the context. For example, if I stick the Products dimension on ROWS, the value of this measure will be different for each row, because each product's earliest order date is different.
That is of course useful, but it's not what I want. Is there some way to force this measure to ignore the query context, and always return the same value?
I looked into SCOPE_ISOLATION and SOLVE_ORDER, but they don't do what I'm trying to do here.
I suppose I could specify a tuple of Dimension1.All, Dimension2.All.... DimensionN.All, covering all dimensions in the cube, but that seems messy and fragile.
I think you might be able to accomplish this with static sets. Here is an example using Adventure Works that produces the same first year regardless of context:
WITH STATIC SET FirstYear AS
HEAD
(
NONEMPTY([Date].[Calendar Year].[Calendar Year].MEMBERS, [Measures].[Internet Sales Amount])
, 1
)
MEMBER FirstYearName AS
FirstYear.ITEM(0).NAME
SELECT
[Measures].[FirstYearName] ON COLUMNS
, [Date].[Calendar Year].[Calendar Year].MEMBERS
//Add as many dimensions as you like here...for example
* [Product].[Product].[Product].MEMBERS
ON ROWS
FROM
[Adventure Works]
;
Example output:
That should hopefully put you on the right track.
Related
I am new to MDX and for now it looks like some hell to me.
I have a measure called Sales KG. It calculate sales amount based on table AData where I have column named Data_Date.
I need to get Sales KG value for specified range of dates.
The problem is I can't understand how to specify that range. It doesn't look like simple < and > are works here.
I totally lost and don't have much to show, but this is what I tried:
select
[Sales KG] on Columns
from [Model]
where ([Format_TT].[Супермаркет], [Data_Date].&[20160101] : [Data_Date].&[20170101])
But it tells me that can't convert string "20160101" into date type. And probably this is not what I want. I want it to be single value for date range in single cell.
What to do?..
Take a look at the below sample they will help .
Please note that "Date" is a dimesnion in the cube, which has an attribute "[Date]" in it. "[Measures].[Internet Sales Amount]" in the cube. It is necessary to have them defined in the SSAS project, If one of them is not defined in the project but exists in the base tables of star schema it will not work. MDX can only see objects defined in the SSAS project
//First way
select
[Measures].[Internet Sales Amount]
on columns
from [Adventure Works]
where {[Date].[Date].&[20130101]:[Date].[Date].&[20130131]}
Second way
select
[Measures].[Internet Sales Amount]
on columns,
{[Date].[Date].&[20130101]:[Date].[Date].&[20130131]}
on rows
from [Adventure Works]
This is a question regarding SSAS Cubes, MDX formulas and Power BI.
I have a measure with the active members per each month. So when I select for example 2018 it shouldn´t aggregate but return the last available month with active members, and if I break down by month it should give the active members for each month.
So I have this formula which works almost fine if querying in MS Management Studio:
with member [Measures].[Last existing SOCIOS] AS
Max(
EXISTING [DIM FECHA].[Jerarquía].[MES NOMBRE].members,
iif([Measures].[ACTIVOS] = 0,null,
[Measures].[ACTIVOS])
)
select {[Measures].[Last existing SOCIOS]} on columns,
[DIM FECHA].[MES NOMBRE].members on rows
from [cubo_Compromisos]
where [DIM FECHA].[AÑO].&[2018]
I would prefer to have the november value returned at the 'All' level. But this is not my main problem. The real issue is that when I use this measure in Power BI it behaves differently: when selecting multiple months it ignores the selected values and just returns the last value for the whole year.
In the screenshot below I have added the value returned by the KPI Card because that is the value that I want returned:
If I select items like this it does it right, but I need it to select all months, and not just one because I am using this measure along others:
Does anyone know the right MDX function to use or an alternative?
Edited: 23-11-2018
It does the same in a Pivot Table connected to a SSAS Cube.When I add the date dimension to the table it works fine. But when using the date dimension and filtering it without the dimension added as rows it returns the value for the whole year.
The function you are looking at is LastChild. Last Child on the upper level of the hierarchy will return the value you are looking at.
I think that function can be used in the Cube design in SSAS - then this will be the standard behavior. If you want to do it with a query you need to do something like:
SELECT [Date].[Fiscal].[Fiscal Quarter].[Q1 FY 2002].LastChild ON 0
FROM [Adventure Works]
To get the last month of the 1st quater (I used example from microsoft and another post on the subject )
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.
I'm having a bit of trouble accomplishing something that I think should be relatively straightforward in MDX. I would like to create a calculated member that provides a sum of one of my measures over the previous two weeks at a given point in time. My time dimension looks like:
TimeId TradingDate Day of Week
-----------------------------------
1000 11/1/2012 Thursday
1001 11/2/2012 Friday
1002 11/5/2012 Monday
1003 11/6/2012 Tuesday
... ...
What makes this particularly difficult is that my Time dimension is not quite complete. The members of my Time dimension only correspond to trading days in the stock market, and not all time. This means that weekends, holidays, or any other day in which the stock market is closed are excluded. This also means the normal methods of traversing time such as LAG or PARALLELPERIOD will not work quite right here. LAG(14), for example, means "14 trading days", which at any given point could represent a variable length of actual time.
Inside my calculated member, I'm attempting to use FILTER in order to get only time members that are within the previous two weeks of the CurrentMember. However, I can't seem to figure out the proper syntax (if there is one) to accomplish this. I imagine it would be something like:
WITH MEMBER [Sum of Price Previous 2 Weeks] AS
SUM(
FILTER(
[Time].[TimeId].Children
, [Time].[TradingDate].MemberValue
>= VBA!DATEADD("ww", -2, [Time].[TradingDate].CurrentMember.MemberValue)
)
, [Price]
)
However, this doesn't quite work. I can't seem to separate the context of the calculated members current iteration from what would be a separate context inside of the FILTER function. In other words, I'm not sure how to say:
"When iterating over the set inside of FILTER, compare the current
member of each iteration against the value of the CurrentMember in
the scope of the calculated member"
Is what I'm trying to accomplish even possible? Is there a different approach I could be taking to accomplish what I'm after?
The result you'll get from a calculated member will depend on the axis of your query. So first, make sure you have [Time].[TradingDate] in your axis.
Second, your [Time].[TradingDate] hierarchy should be ordered by Key (I assume TradingDate is the key).
Now you can use this member definition:
WITH MEMBER [Sum of Price Previous 2 Weeks] AS
SUM(
[Time].[TradingDate].CurrentMember.Lag(14):[Time].[TradingDate].CurrentMember, [Price]
)
You can use set aliases to refer to the outer CurrentMember in the Filter context:
WITH MEMBER [Sum of Price Previous 2 Weeks] AS
SUM(
GENERATE([Time].[TradingDate].CurrentMember AS CurrentDateAlias,
FILTER(
[Time].[TimeId].Children
, [Time].[TradingDate].MemberValue
>= VBA!DATEADD("ww", -2, CurrentDateAlias.Item(0).MemberValue)
)
)
, [Price]
)
GENERATE is used just to define the alias somewhere.
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