I have a bunch of calculated measures which I understand are executed only at query time. Unlike the derived measures which are pre-aggregated during cube processing time and thereby giving a better query performance the calculated measures aren't pre-aggregated and hence have the potential for a bad performance.
Are there any tips or tricks to decrease the query time of calculated measures in SSAS cubes?
I already created partitions on my measure groups and this helped in reducing the cube perofrmance time. But now I want to go a step further and reduce the query time for the calculated measures.
I hear something about aggregations and named sets that can help with this. But couldn't find anything online with a god tutorial on how to do this.
Updated:
Here are the calculated measures I'm currently using in my cube
[Total Activities]
[Measures].[Day1] + [Measures].[Day2] + [Measures].[Day3]
[Total Days Engaged]
IIF([Measures].[Day1] > 0 , 1, 0) + IIF([Measures].[Day2] > 0 , 1, 0) + IIF([Measures].[Day3] > 0 , 1, 0)
[Avg Days Engaged Per Users]
IIF([Measures].[USER COUNT] = 0, 0 , [Measures].[Total Days Engaged]/[Measures].[USER COUNT])
[Avg Requests Per User]
IIF([Measures].[USER COUNT] = 0, 0 ,[Measures].[Total Activities]/[Measures].[USER COUNT])
[Daily Engaged Users]
SUM([Dim User].[Id].[Id], IIF([Measures].[Total Days Engaged] > 2, 1, 0))
Related
I am newbie to SSAS cube and need some help. I have a cube created from a fact table and one of the measure, lets call it amount, contains zeros. This measure was created as a SUM.
Now I also have the Count measure added by SSAS designer.
What I need is the count of all non zero amount.
I tried to add a calculated measure as
`IIF([Measures].[amount] > 0,[Measures].[RowCount],null)`
also tried
FILTER([Measures].[RowCount],[Measures].[Amount] > 0)
Both these returns the count including the amount=0.
I am validating it via SSMS sql query
SELECT count(*)
FROM [dbo].[Fact_Session]
where SiteKey = 5 and DateKey = 20170201
and Amount >0
Any help is appreciated. My assumption is that the IIF/Filter statement will operate on the individual rows before cubing, as once aggregated into a dimension, the amount will not be 0 due to the aggregation . Please Help.
To count non-zero you can use this approach:
WITH
MEMBER [Measures].[IsNotEmpty] AS
IIf(
Not(IsEmpty([Measures].[Amount]))
,1
,Null
)
But better to do this inside a SUM over a particular set - so the following counts how many subcategories are not empty:
WITH
MEMBER [Measures].[SubCategory_IsNotEmpty] AS
SUM(
[Product].[Product Categories].[SubCategory].members
,IIf(
Not(IsEmpty([Measures].[Amount]))
,1
,Null
)
)
Let's assume i have easy table with sales data like:
id shop
id product
date
amount
Can you help me to write MDX query for calculated member to get current period sales ratio to same period of previous year?
For example, if month or quarter selected as one of dimensions.
Let's assume you've a [Time] dimension with [Year], [Month] and [Day] levels.
If
SELECT
[Time].[Jan 2015]:[Time].[Dec 2015] on 0,
[Measures].[Sales] on 1
FROM
[Cube]
Returns the sales for all months of 2015. We can add a calculated measure to get ratio :
WITH
MEMBER [Sales Ratio] AS DivN(
[Sales],
( ParallelPeriod( [Time].[Year], 1, [Time].current ), [Sales] )
SELECT
[Time].[Jan 2015]:[Time].[Dec 2015] on 0,
{[Sales],[Sales Ratio]} on 1
FROM
[Cube]
DivN is icCube specific and allows for dividing being 'empty' safe.
ParallelPeriod is a standard MDX function, that returns previous years month. You could also use Lag(-12), that is 'travelling' backwards in a level 12 times.
current (aka Currentmember) is also standard MDX and allows for retrieving the current value of a hierarchy/ dimension.
In icCube I'd add a function to navigate to the previous year so you can reuse it (and fix one if needed). Like :
WITH
FUNCTION timePrevYear(t_) AS ParallelPeriod( [Time].[Year], 1, t_ )
MEMBER [Sales Ratio] AS DivN(
[Sales],
( timePrevYear( [Time].current ), [Sales] )
SELECT
[Time].[Jan 2015]:[Time].[Dec 2015] on 0,
{[Sales],[Sales Ratio]} on 1
FROM
[Cube]
It's going to be a bit too much but eventually you could add this kind of calculations in what we call in MDX Utility or Stats dimension, so you can even let the end-user select this in a dropdown from a reporting tools. More on this here.
In the models I create for my clients, I sometimes take another route as ic3 has suggested:
Especially when there will be lots of additional calculations on top of these (e.g. year-to-date, inception-to-date, month-to-date etc).
This is:
load the same facts data again, but set as the "load date" the "date" - 1 year (e.g. mySQL: DATE_ADD(,INTERVAL -1 YEAR).
Advantages:
drill through on history is possible
lots of formulas can be added "on top" of these, you always know that the basics are ok
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.
I looked at this topic, Calculating the number of days in a time dimension node - with Grand Total, but can't seem to get it.
I have a Time Dimension; [Invoice Date].
I want to count the number of Work Days in that dimension for a specified time period. I'm new to MDX.
Here's what I have.
Count(
Descendants(
[Invoice Date].CurrentMember,
[Invoice Date].[Work Date].[Work Date]
)
)
I'm getting a cube error now.
An easy way to implement this reliably would be to create a physical measure "Day Count". To do this, create a new measure group on the Date dimension table, and define "Day Count" as the Count. On the dimension usage tab, make sure you set a relationship from this measure group to the Invoice Date cube dimension and not the other dimensions.
A simple cube has 1 measure and three time dimensions:
[Measures].[Amount Paid]
[Date Paid]
[Cover Start Date]
[Cover End Date]
Earned Premium =
0% if Cover Start Date is before the period in question
100% if Cover End Date has passed
else [Cover End - Cover Start] * Days Since Start
For any given cell, how do I traverse all the start and end dates and determine what the amount earned for a period is?
I assume other dimension are missing, e.g. one like [ContractId], if no what comes after doesn't make real sense.
The problem here is that your actual measure,earned premium, is a function (Amount Paid, Cover Start Date, Cover End Date, date) and this for each deal. You can not aggregate over a set of deals at once as the function is not associative - or something like this :-).
So I would feed my cube with the premium for each deal over the period [Cover Start Date], [Cover End Date] with the daily premium for this contract. Once you've this you can easily aggregate this measure over your dimensions. -> Now daily premium is not anymore a function of Cover dates..
MDX is not a real calculation engine, so you're pushing the system out of it's limit. Solving this with scopes, calculated measures can produce an amazingly slow cube...