How is it possible to do an dynamic histrogram using MDX ?
For example, our schema is based on web visits, we've the number the sessions and the number of click-outs. We would like to have the number of session with one click-out taking into account that this might depend on other dimensions (country, hour, entry-page...).
To solve this we are going to work with two different concepts. First create a new Hierarchy and afterwards use MDX+.
First we've to create a new dimension, [Histrogram]. This new dimension will contain the defintion of the buckets with two member properties : start-bucket and end-bucket. A pseudo table that looks like
Name start-bucket end-bucket
0-1 0 1
1-2 1 2
2-3 2 3
...
10++ 10 2147483647
This Hierarchy is not linked to the facts and defines for each member two properties defining a bucket.
Let's put this to use in MDX.
Let's assume we've a dimension, [Sessions], and a measure, [click-outs]. First we're going to use the OO features of icCube and create a vector that for each session calculates the number of [click-outs]
-> Vector( [Sessions], [click-outs], EXCLUDEEMPTY )
Vector has a function, hist(start,end), that does exactly what we need and is counting all occurencies between start and end (excluded).
Vector( [Sessions], [click-outs], EXCLUDEEMPTY )->hist(0,1)
Putting this together with our newly created hierarchy allows to automize the calculation for all buckets. The const function ensures the vector is calculated only once as it might be time consuming.
The final MDX looks like (note that both function and calc. members could be created in the schema script, once per schema):
WITH
CONST FUNCTION ClicksBySession() AS Vector( [Sessions], [Measures].[click-outs], EXCLUDEEMPTY )
MEMBER [Session/Clickout] AS ClicksBySession()->hist( [Histogram].currentMember.properties("start-bucket", TYPED) , [Histogram].currentMember.properties("end-bucket", TYPED)
SELECT
{[Session/Clickout] } on 0,
[Histogram].on 1
FROM [clickout]
--where [Geography].[Europe]
And there you've an histrogram that is calculated dynamically that can be easily inserted in a dashboard and reused.
Related
I need to create a new measure that is a derivative of a preexisting measure. The preexisting measure is just a straight count of all rows. The new measure is a count of all rows where EventType != 3 or 4 and then that count is divided by the preexisting measure count to produce a %. See data and questions below for context.
ID-------DimDateKey------EventType
1-------20220101-----------3
2-------20220101-----------2
3-------20220101-----------4
4-------20220101-----------1
5-------20220101-----------3
6-------20220101-----------4
Preexisting measure- straight count of all rows - 6
Needed Measure – count of all rows where Eventype not in (3,4) / Prexisting measure: 2/6=.333
(It needs to be filterable by all associated dimensions like DimDateKey)
Do I need to create a new Data source view to generate a count of these rows where EventType is not in(3,4), or can I define this as a temporary subset in the calculations tab of a Multidimensional Cube?
Once I have reached the step where new Measure/preexisting measure, what is that logic supposed to look like in Calculations? I see other measures are generated through being divided in Calculations, but if I try to test similar syntax in a MDX query I can’t get it to return anything but an error.
Lastly, once the new count is divided by the old count it should still be filterable by all of the dimensions that each count has a relationship with, correct?
In my simple cube, I have a measure = \[Measure\].\[Salary\], I have also \[DimEmpployee\].\[EmployeeLastName\].\[Smith\]. I would like to create calculated measure, where I can display in Axis 0 two measures - \[Measure\].\[Salary\] and calculated measure \[Measure\].\[SmithsSalaries\], to compare difference between Smith's earnings vs Total Salary.
I would like to compare Measure.SmithSalaries with other measures accross all diemensions. Is it possible to create such a measure using SCOPE statement?
I was playing around SCOPE statements, but it was displaying results only if DimEmployee was selected. I am looking for something which is running in blocks to avoid performance issues.
I think you only need a simple calculated measure.
CREATE MEMBER CURRENTCUBE.[Measures].[SmithSalaries]
AS ([DimEmployee].[EmployeeLastName].[Smith], [Measures].[Salary]),
VISIBLE = 1 ;
After that you can combine that with you total salary for example to get a ratio.
CREATE MEMBER CURRENTCUBE.[Measures].[SmithSalaries Ratio]
AS DIVIDE(([DimEmployee].[EmployeeLastName].[Smith], [Measures].[Salary]),[Measures].[Salary])
VISIBLE = 1 ;
SCOPE allows you to have different behaviors when different combinations of Dimensions are into play, like returning a different calculation when the DimEmployee is selected but otherwise just return the normal calculation. Like a Very efficient IF condition to check what are in the Axis of this calculation.
I am trying to replicate the following sql statement into MDX so that I can create a calculated member in the cube using the base loaded members instead of having to calculate it outside the cube in the table and then loading it
SUM(CASE WHEN ((A.SALES_TYPE_CD = 1) AND (A.REG_SALES=0))
THEN A.WIN_SALES
ELSE 0
END) AS Z_SALES
I am currently loading SALES_TYPE_CD as a dimension and REG_SALES and WIN_SALES as measures.
I also have a few other dimensions in the cube but for simplicity, lets just say I have 2 other dimensions, LOCATION and ITEM
The dimension has LOCATION has 3 levels, "Region"->"District"->"Store", ordered from top to bottom level.
The dimension has ITEM has 3 levels, "CLASS"->"SUBCLASS"->"SKU", ordered from top to bottom level.
The dimension has SALES TYPE has 2 levels, "SALES_TYPE_GROUP"->"SALES_TYPE_CD", ordered from top to bottom level.
I know that I cannot create a simple calculated member in the cube which crossjoins the "SALES_TYPE" dimension with another dimension to get the answer I want.
I would think that it would be a more complicated MDX statement something like :
CREATE MEMBER CURRENTCUBE.[Measures].[Z_Sales]
AS 'sum(filter(crossjoin(leaves(), [Sales Type].[Sales Type].
[Sales_Type_CD].&[1]), [Measures].[REG_SALES]=0),[Measures].
[WIN_SALES])',
FORMAT_STRING = '#,#',
VISIBLE = 1 ;
But this does not seem to return the desired result.
What would be the proper MDX code to generate the desired result?
I did a bunch of testing with the data and I now know that there is no way I can get the right answer by using MDX alone in this scenario. Like "Greg" and "Tab" suggested, the only way would be to have reg sales as a dimension. Since this is a measure, that is out of the question because of the large number of possibilities for the value which has a data type of decimal (18,2)
Thanks for taking the time to answer the question.
I have a measure [Measures].[myMeasure] that I would like to create several derivatives of based on the related attribute values.
e.g. if the related [Location].[City].[City].Value = "Austin" then I want the new calculated measure to return the value of [Measures].[myMeasure], otherwise, I want the new calculated measure to return 0.
Also, I need the measure to aggregate correctly meaning sum all of the leaf level values to create a total.
The below works at the leaf level or as long as the current member is set to Austin...
Create Member CurrentCube.[Measures].[NewMeasure] as
iif(
[Location].[City].currentmember = [Location].[City].&[Austin],
[Measures].[myMeasure],
0
);
This has 2 problems.
1 - I don't always have [Location].[City] in context.
2. When multiple cities are selected this return 0.
I'm looking for a solution that would work regardless of whether the related dimension is in context and will roll up by summing the atomic values based on a formula similar to above.
To add more context consider a transaction table with an amount field. I want to convert that amount into measures such as payments, deposits, return, etc... based on the related account.
I don't know the answer but just a couple of general helpers:
1 You should use IS rather than = when comparing to a member
2 You should use null rather than 0 - 0/NULL are effecitvely the same but using 0 will slow things up a lot as the calculation will be fired many more times. (this might help with the second section of your question)
Create Member CurrentCube.[Measures].[NewMeasure] as
iif(
[Location].[City].currentmember IS [Location].[City].&[Austin],
[Measures].[myMeasure],
NULL
);
How can create generic calculated member which i can reuse in order to calculate the statistical deviation on any logical related dimension(s) and measurement ? I need to be able to select any dimension and measure.
I found related discussion here from which i took stdDev function example.
I've created the calculation, but the result it empty.
CREATE MEMBER CURRENTCUBE.[Measures].calcTest
AS iif(IsEmpty(Axis(0).Item(0)), NULL,
StdDev(Axis(1).Item(0).Item(0).Dimension.Children, Axis(0).Item(0))),
FORMAT_STRING = "#,##0.00;-#,##0.00",
VISIBLE = 1 , ASSOCIATED_MEASURE_GROUP = 'TestMeasure' ;
If you want to use it for all measures, you would put your calcTest member to another hierarchy not used in the query, maybe an utility hierarchy (see below), and then reference the Measures.CurrentMember instead of Axis(0).Item(0).
To get the calculation generalized for all hierarchies except the measures is hard, as somewhere you have to tell the calculation which hierarchy to use. And to do this in the cube before the query is defined cannot be done. Hence, the approach to use the leftmost hierarchy in the rows (Axis(1).Item(0)) taken in your question can be changed to reference something different in the query, but cannot be completely flexible. Of course, an approach could be to define, say, three similar members, one for the first, one for the second, and one for the third hierarchy in the rows.
For the utility hierarchy, you would create a dimension table with just one row and one column. Let's say the data content of this column in the single row is "-standard-"and reference this single member in all fact tables from an additional foreign key. Then you build the dimension into the cube with the references from all measure groups. Lets say the attribute hierarchy is called [Utility].[Utility]. Make the attribute hierarchy non aggregatable, and set the default member to the "-standard-" member. In the calculation script, you can then add members to this utility dimension like
CREATE MEMBER [Utility].[Utility].StdDevRows1 // StdDev for leftmost hierarchy in the rows
AS StdDev(Axis(1).Item(0).Item(0).Dimension.Children, Measures.CurrentMember),
FORMAT_STRING = "#,##0.00;-#,##0.00",
VISIBLE = 1 , ASSOCIATED_MEASURE_GROUP = 'TestMeasure' ;
CREATE MEMBER [Utility].[Utility].StdDevRows2 // StdDev for second hierarchy in the rows
AS StdDev(Axis(1).Item(1).Item(0).Dimension.Children, Measures.CurrentMember),
FORMAT_STRING = "#,##0.00;-#,##0.00",
VISIBLE = 1 , ASSOCIATED_MEASURE_GROUP = 'TestMeasure' ;
CREATE MEMBER [Utility].[Utility].StdDevRows3 // StdDev for third hierarchy in the rows
AS StdDev(Axis(1).Item(2).Item(0).Dimension.Children, Measures.CurrentMember),
FORMAT_STRING = "#,##0.00;-#,##0.00",
VISIBLE = 1 , ASSOCIATED_MEASURE_GROUP = 'TestMeasure' ;
The advantage of a separate utility hierarchy is that you can combine it with all measures, times, etc., as it is not itself a member of these.