I have a cube with a typical snapshot structure and daily granularity (like inventory quantities). I would like to be able to remove some of the granular data from this cube, because we have something like 270,000,000 rows of source data, cube processing is slow, and there isn't a meaningful difference from one data point to the next, at the day level.
However, users want a graduated level of detail - daily detail for the recent past, then monthly or quarterly for older periods. Doing that would help the situation BUT - they also want charts that "appear" to show data for each data point and not have "holes" between one data point and the next.
So here's the question: if I have a cube with a snapshot fact table, and the table has daily values for the most recent 30 days, then monthly values for 6 months, then quarterly values for two years prior, is there any sane way to make output from the cube "spoof" the gaps, by repeating the last snapshot value for each "empty" day? In other words, if I deliver a chart over the whole time period, I want it to have plateaus that repeat the last non empty value across each gap in the data, but without incurring the storage penalty of keeping all those values.
You could in the cube use a MDX calculated measure for day level, which looks up the last available data point.
Not sure if that idea helps, but that's where I would start looking.
I am close on this. Came up with the following type of recursive expression, which seems to work (mostly). Tried to substitute in the ClosingPeriod() function to tidy it up, but that bit doesn't work:
/* Works! */
with member Measures.lastEstatementsCount as
iif(
isleaf( [Date].[Calendar].currentmember ),
iif(
isempty([Measures].[_Add E Statements Count]),
( [Date].[Calendar].prevmember, Measures.[lastEstatementsCount] ),
Measures.[_Add E Statements Count]
),
(
( tail( descendants( [Date].[Calendar].currentmember ) ) ).item(0),
Measures.[lastEstatementsCount]
)
)
select
Measures.lastEstatementsCount on columns,
[Date].[Calendar].[Month Name] on rows
from [EngagedMember];
/* Substituting ClosingPeriod() in the recursion doesn't for some reason */
with member Measures.lastEstatementsCount as
iif(
isleaf( [Date].[Calendar].currentmember ),
iif(
isempty([Measures].[_Add E Statements Count]),
( [Date].[Calendar].prevmember, Measures.[lastEstatementsCount] ),
Measures.[_Add E Statements Count]
),
(
ClosingPeriod( [Date].[Calendar].[Date], [Date].[Calendar].currentmember ),
Measures.[lastEstatementsCount]
)
)
select
Measures.lastEstatementsCount on columns,
[Date].[Calendar].[Month Name] on rows
from [EngagedMember];
Related
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 )
I am trying to create dynamic Time Intelligence in SSAS Tabular similar to traditional OLAP Time Intel.
Additionally, I need Time Intelligence that can handle two sets of date hierarchies. For example, a Transmission Date and an Activity Date.
For example, I am trying to create a simple year-to-date sum of gross sales given that the user has selected two filters in an Excel pivot table. We are talking about all dates of transmission but only from the point of view of a single activity date. That is, I want to view 2016 total sales as if it were today, but also as if it were last month (i.e. as of a month ago, what did sales look like?).
An additional caveat is that I need two special calendars: a radio broadcast calendar for the transmission period and a traditional gregorian for the activity period.
I have started here:
YTD :=
IF (HASONEVALUE ( Dates[Years-Bcast] ),
CALCULATE (
SUM ( Sales[Sales Amount] ),
FILTER (
ALL( Dates ),Dates[Years-Bcast] = VALUES ( Dates[Years-Bcast] )
&& Dates[DatesKey] <= MAX ( Dates[DatesKey] )
)
),
BLANK ()
)
The problem I assume is my filter; I really want the last FILTER clause to be:
&& Dates[ActivityDateKey] <= MAX ( Dates[DatesKey] )
The activity date would be a user-defined report filter. It seems I need 2 filters. The first filter is filtering out only the applicable transmission dates I need, so then my activity date filter is pointless.
Any help would be greatly appreciated.
this might be what you're looking for..
KEEPFILTERS - https://msdn.microsoft.com/en-us/library/hh758426.aspx
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
Im trying to create a daily calculation in my Cube or an MDX statement that will do a calculation daily and roll up to any dimension. I've been able to successfully get the values back, however the performance is not what I think it should be.
My fact table will have 4 dimensions 1 of which being daily date (time). I have a formula that uses 4 other measures in this fact table and those need to be calculated daily and then geometrically linked across the time dimension.
The following MDX statement works great and produces the correct value but it is very slow. I have tried using exp(sum(log+1))-1 and multiply seems to perform a little better but not good enough. Is there another approach to this solution or is there something wrong with my MDX statement?
I have tried defining aggregations For [Calendar_Date] and [Dim_Y].[Y ID], but it does not seem to use these aggregations.
WITH
MEMBER Measures.MyCustomCalc AS (
(
Measures.x -Measures.y
) -
(
Measures.z - Measures.j
)
)
/
Measures.x
MEMBER Measures.LinkedCalc AS ASSP.MULTIPLY(
[Dim_Date].[Calendar Date].Members,
Measures.MyCustomCalc + 1
) - 1
SELECT
Measures.LinkedCalc ON Columns,
[Dim_Y].[Y ID].Members ON Rows
FROM
[My DB]
The above query takes 7 seconds to run w/ the following number of records:
Measure: 98,160 records
Dim_Date: 5,479 records
Dim_Y: 42 records
We have assumed that by defining an aggregation that the amount of calculations we'd be performing would only be 42 * number of days, in this case a maximum of 5479 records.
Any help or suggestions would be greatly appreciated!
I'm trying to set up a cube calculation. My current remit is that I will receive exchange rates, and these will be sent at the start of the month. Sometimes they will change during the month, and I will receive a rate to use for that currency onwards.
The initial problem is that LastNonEmpty uses the granularity questioned, which means when I query by day most days do not have exchange rates, so the calculations fail. I replaced the exchange rate measure, initially with a recursive calculation, but later with the following:
WITH
MEMBER [Measures].[EOD]
AS
Aggregate({NULL:[Date].[Calendar Y M D].CurrentMember}, [Measures].[End Of Day Rate])
So, when viewed on the date dimension, it will get the most recent exchange rate. This allows a daily calculation as follows:
MEMBER [Measures].[Converted]
AS
SUM
(
{[Currency].[Currency].[Currency] * [Date].[Calendar Y M D].CurrentMember},
(
(
[Measures].[Sales]
)
/ [Measures].[EOD]
)
)
Lastly I use this in a query:
SELECT
{
[Measures].[Converted]
}
ON COLUMNS,
NON EMPTY
{
[Date].[Calendar Y M D].[Calendar Day].&[2010-Q3-08-01] :
[Date].[Calendar Y M D].[Calendar Day].&[2010-Q3-08-31]
}
ON ROWS
FROM [Cube]
This all works fine, but ideally I'd prefer to query by year/month, as these are month-end reports. I can sum all this in the code tiers, but I'd rather have MDX that can do it itself.
The problem is that the calculations are done almost recursively at the day-level, then I'd like them rolled up to the month (Or even year) level.
I did try the currency conversion wizard, swapping the exchange rate for the time-aggregated one above, but attempting to browse the cube in SSMS locked the server as it tried to do the aggregation for the whole calendar :(
Any suggestions on what approach is best to take?
If you used views or named queries in the DSV instead of tables, then you could adjust the view or named query to limit the data to days where you have loaded exchange rate data. I'm not sure if this would meet your business need, but you could eliminate the empty data issues through this approach. After all, there's not much use to loading data that doesn't contain a value or, worse, preloading a guestimated exchange rate that would have to be overwritten once the actual numbers are available.