Order of statement execution - mdx

Suppose I run a SUM function on some set inside a WITH MEMBER construct. In the WHERE clause I limit, narrow down the size of the set (by date, for example). Would calculations in WITH MEMBER run for the entire set, or does the interpreter know about the narrowing down ahead of time and so would not waste CPU cycles doing all the calculations for an entire set?
WITH MEMBER Measures.[Summed] AS
SUM(
{[Sample].[Sample ID].[Sample ID]},
[Measures].[Value]
)
SELECT {[Measures].[Value], Measures.[Summed]} ON 0
FROM [A Cube]
WHERE([Dim Date].[ymd].[Date Name].&[01 Apr 2016]
The query will display results for April 1, 2016. But would it run the calculations for all dates before doing so? Or would it be efficient?

Related

DATEIME_DIFF throwing error when using safe divide

I've created a query that I'm hoping to use to fill a table with daily budgets at the end of every day. To do this, I just need some simple maths:
monthly budget / number of days left in the month.
Then, at the end of the month, I can SUM all of the rows to calculate an accurate budget.
The query is as follows:
SELECT *,
ROUND(SAFE_DIVIDE(budget, DATETIME_DIFF(CURRENT_DATE(), LAST_DAY(CURRENT_DATE()), DAY)),2) AS daily_budget
FROM `mm-demo-project.marketing_hub.budget_manager`
When executing the query, my results present as negative numbers, which according to the documentation for this function, is likely caused by the result overflowing the result type.
View the results of the query.
I've made a fools guess at rounding the calculation. Needless to say that it did not work at all.
How can I stop my query from returning negative number?
use below
SELECT *,
ROUND(SAFE_DIVIDE(budget, DATETIME_DIFF(LAST_DAY(CURRENT_DATE()), CURRENT_DATE(), DAY)),2) AS daily_budget
FROM `mm-demo-project.marketing_hub.budget_manager`

Using a date range in calculated member in MDX query for Tabular cube model

I have a requirement where I have to get the values of different measure with each measure having its own date range, the following query works and gets me the data over an year,
WITH MEMBER [Measures].[Ex1] AS ([Measures].[Average Spending], [Date].[Year].&[2020])
MEMBER [Measures].[Ex2] AS ([Measures].[Average Time Spent], [Date].[Year].&[2019])
SELECT {[Customer].[Name].[Name]} ON 1, {[Measures].[Ex1],[Measures].[Ex2]} ON 0 FROM [Model];
but when I try to pass a date range instead of year, I'm getting an error,
WITH MEMBER [Measures].[Ex1] AS ([Measures].[Average Spending], [Date].[Year].&[2020])
MEMBER [Measures].[Ex2] AS ([Measures].[Average Time Spent], [Date].[Date].[01-May-2020]:[Date].[Date].[31-May-2020])
SELECT {[Customer].[Name].[Name]} ON 1, {[Measures].[Ex1],[Measures].[Ex2]} ON 0 FROM [Model];
I'm getting the following error,
Executing the query ... The function expects a string or numeric
expression for the argument. A tuple set expression was used. Run
complete
How do I get the measure for a date range for each calculated member?
If you do not use a tuple (i. e. a combination of single members of the hierarchies like Measures or Year), but a set, then you need to tell MDX what to do with the set elements to get to a single value. I would assume the following will give what you want:
WITH
MEMBER [Measures].[Ex2] AS
Aggregate([Date].[Date].[01-May-2020]:[Date].[Date].[31-May-2020],
[Measures].[Average Time Spent]
)
...
Instead of Aggregate, you could also use Sum, Avg, Variance etc. but normally, I prefer using Aggregate, as this uses whichever aggregation method is defined for the measure in the cube, i. e. it is more universal, and the query does not need to be adapted to changes in the cube calculation scripts.
See also Aggregate in the SSAS documentation

MDX - Filter different measures using different date intervals

This is similar to another question I made (MDX - Running Sum over months limited to an interval) but I feel that I was going off track there.
Let me start again.
I have a calculated measure
MEMBER [Measures].[m_active] AS ([Measures].[CardCount], [Operation].[Code].[ACTIVATION])
That I want to filter on a short interval (let's say from 10 January 2016 to 20 August 2017, those are parametrized)
and another calculated measure that i want to filter since the beginning of date dimension (1st January 2010) to the end of last filter (20 August 2017 in this case), this measure is running sum of all the precedent
MEMBER [Measures].[tot_active] AS (
SUM({[Calendar.YMD].[2010].Children}.Item(0):[Calendar.YMD].CurrentMember, ([Measures].[CardCount], [Operation].[Code].[ACTIVATION]))
On the columns I have this calculated dimensions and on the rows I have months (in the small interval range) and another dimension crossjoined
SELECT
{[Measures].[m_active], [Measures].[tot_attive]} ON COLUMNS,
NonEmptyCrossJoin(
{Descendants([Calendar.YMD].[2016].[Gennaio]:[Calendar.YMD].[2017].[Agosto], [Calendar.YMD].[Month])},
{Descendants([CardStatus.Description].[All CardStatus.Descriptions], [CardStatus.Description].[Description])}
) on ROWS
If I put a date range in the WHERE clause the first member is perfect but i ruin the second, how can I make the second member ignore the WHERE clause? Or is there another solution?
Without testing I'm a little bit unsure of the behaviour, but did you try moving the filter from a WHERE clause into a subselect?
Subselects are formed like this:
...
FROM (
SELECT
<date range for filter> ON 0
FROM cubeName
)

SSAS Daily Calculation Rolled up to Any Dimension

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!

How do I perform an "average days since event" type query in mdx?

I have a cube that I have in the past used to report on counts of events. Let's say for the month of July I want to break down the number of events that have occurred for each product.
I'd have something like this:
SELECT Measures.[Count] ON COLUMNS,
Product.[Product Id].Members ON ROWS
FROM [MyCube]
WHERE [Time].[Month].[July 2012]
With an output like:
Count
Car 5
Train 6
Now I want to modify the output to get something like this:
Count Avg Days since sale
Car 5 12
Train 6 14
How do I do that?
I've spent a few hours trying to find a solution to this in MDX, but can't find a way to do this. (I'm very new to MDX)
I've found several solutions that would work if I included days in either COLUMNS or ROWS.
For instance:
WITH MEMBER Measures.[NumDays] as
count([Time].[Date].CurrentMember :
[Time].[Date].&[2012-07-27T00:00:00])
SELECT
([Time].[Date].Members,{Measures.[Count],Measures.[NumDays]}) ON COLUMNS,
[Product].[Product Id].Members ON ROWS
FROM [MyCube]
WHERE [Time].[Month].[July 2012]
This gets me really close. The result is something like:
July 1 July 2 ...
Count Num Days Count Num Days ...
Car 1 24 3 23
Train 0 24 1 23
I could use this result set and get what I want in my .NET code. I can calculate the average days since sale by weighted average.
For car, for instance, it would be (1*24 + 3*23)/(1 + 3). I'd have to do some mangled and unfortunate things in my .NET code to get this to work, and I'd also have to send back about 80 times as much data from the server as I need.
The problem I've been running into with MDX is that as soon as I take away [Time].[Date].Members from the result set, [Time].[Date].CurrentMember is [Time].[Date].All, and I can't do any meaningful calculations from it.
Is there a way to use the second MDX as a subquery, and rollup the values it returns in the way I need to?
The subquery approach isn't necessary for my solution, but I am curious if that can be done. Any help would be appreciated. Thanks in advance.
You can use the Sum function:
WITH MEMBER [Measures].[NumDays] AS
Count([Time].[Date].CurrentMember :
[Time].[Date].&[2012-07-27T00:00:00])
MEMBER [Measures].[avg] AS Sum([Time].[Date].Members, Measures.[Count] * [Measures].[NumDays])/ Sum([Time].[Date].Members, Measures.[Count])
SELECT
{[Measures].[avg]} ON COLUMNS,
[Product].[Product Id].Members ON ROWS
FROM [MyCube]
WHERE [Time].[Month].[July 2012]
When you remove [Time].[Date].Members from your second query, the current member on the hierarchy retated to [Time].[Date] is the default member (which is the All member).