I have a day level in my time dimension.
I want to output the sum/avg for a selected range of days like in the following statement:
WITH
MEMBER measures.[sum1] AS
Sum([Measures].[Menge_Artikel_Stk])
MEMBER measures.[sum2] AS
Sum
(
[D_Datum].[Datum].[Tag]
,[Measures].[Menge_Artikel_Stk]
)
SELECT
{
[Measures].[stock]
,[Measures].[sum1]
,[Measures].[sum2]
} ON 0
,NON EMPTY
CrossJoin
(
{[D_item].[itemno].[itemno].MEMBERS}
,{
[D_Date].[Date].[day].[30.01.2017] : [D_Date].[Date].[Day].[05.02.2017]
}
) ON 1
FROM [Cube];
My goal is to show the sum/avg along the date-dimension filtered on rows.
Instead of 40/1653 i want sum to display 250 for the sum or 35,7 for the average. (1653 is obviously the sum of the entire day level). I want to add this calculated member to an Excel-Sheet. Thus the time range set is variable.
To get the sum/avg rows across the specific range you can do something like this:
WITH
MEMBER measures.[sum1] AS
Sum([Measures].[Menge_Artikel_Stk])
MEMBER measures.[sum2] AS
Sum
(
[D_Datum].[Datum].[Tag]
,[Measures].[Menge_Artikel_Stk]
)
MEMBER [D_Date].[Date].[All].[DaySum] AS
Sum
(
[D_Date].[Date].[day].[30.01.2017] : [D_Date].[Date].[Day].[05.02.2017]
)
MEMBER [D_Date].[Date].[All].[DayAvg] AS
Avg
(
[D_Date].[Date].[day].[30.01.2017] : [D_Date].[Date].[Day].[05.02.2017]
)
SELECT
{
[Measures].[stock]
,[Measures].[sum1]
,[Measures].[sum2]
} ON 0
,NON EMPTY
CrossJoin
(
{[D_item].[itemno].[itemno].MEMBERS}
,{
{
[D_Date].[Date].[day].[30.01.2017] : [D_Date].[Date].[Day].[05.02.2017]
}
,[D_Date].[Date].[All].[DaySum]
,[D_Date].[Date].[All].[DayAvg]
}
) ON 1
FROM [Cube];
You can use the Axis function to define the current set on your axis:
WITH
MEMBER measures.[sum] AS
Sum(
Axis(1),
[Measures].[Menge_Artikel_Stk]
)
MEMBER measures.[avg] AS
AVG(
Axis(1),
[Measures].[Menge_Artikel_Stk]
)
SELECT
{[Measures].[Menge_Artikel_Stk],[Measures].[sum],[Measures].[avg]} ON 0,
NON EMPTY {[D_Date].[Date].[day].[30.01.2017]:[D_Date].[Date].[Day].[05.02.2017]} ON 1
FROM [Cube];
Related
in MDX I would like to create a select which returns a 2x2 array, filled with hard coded values.
Here is an attempt:
WITH
MEMBER a AS 1
MEMBER b AS 2
SET un AS { a , b }
SELECT { un} ON 0,
[Dim misc].[Gender].[(All)] ON 1
FROM [my cube]
it returns:
but I would like it to return an other row, with other values than 1,2.
You have solved half the problem already. However defining a set is not necessary.
You need to do the following
Use defaultmember,
Use Case
Define a dummy member for the dimension you use.
Instead of Set just define members.
Take a look at the example below based on adventure works.
with
member Column1Row1 as 1
member Column2Row1 as 2
member Column1Row2 as 3
member Column2Row2 as 4
member Column1 as case when [Product].[Product].currentmember is [Product].[Product].defaultmember then Column1Row1 else Column1Row2 end
member Column2 as case when [Product].[Product].currentmember is [Product].[Product].defaultmember then Column2Row1 else Column2Row2 end
member [Product].[Product].[Row2]
as [Product].[Product].defaultmember
select
{Column1,Column2} on 0,
{
[Product].[Product].defaultmember,
[Product].[Product].[Row2]}
on 1
from
[Adventure Works]
Result
I am using sharepoint report builder.
In my data (se picture below) - I would like to get all the first row - the ones with yellow.
How do i do that.
Here is the MDX code. What should I write to get the yellow rows?
SELECT
NON EMPTY
{[Measures].[Antal unikke brugere - Visiteret Tid]} ON COLUMNS
,NON EMPTY
{
[Borger].[Anonym Borgernøgle DPR].[Anonym Borgernøgle DPR].ALLMEMBERS*
[SundhedOgOmsorg - Ydelse].[Ydelse].[Ydelse].ALLMEMBERS*
[Kalender].[År].[År].ALLMEMBERS*
[Kalender].[Måned].[Måned].ALLMEMBERS
}
DIMENSION PROPERTIES
MEMBER_CAPTION
,MEMBER_UNIQUE_NAME
ON ROWS
FROM
(
SELECT
{
[SundhedOgOmsorg - Ydelse].[Ydelse].&[12.1 Hjemmetrænerforløb]
,[SundhedOgOmsorg - Ydelse].[Ydelse].&[12.2 Komb. Hjemmetræner & Terapeutforløb]
,[SundhedOgOmsorg - Ydelse].[Ydelse].&[12.3 Komplekse Rehabiliteringsforløb]
,[SundhedOgOmsorg - Ydelse].[Ydelse].&[12.7. hverdagsrehab. revis.gr. m. tp.]
} ON COLUMNS
FROM
(
SELECT
{[SundhedOgOmsorg - Modul].[Modul].&[Hjemmehjælp]} ON COLUMNS
FROM [FrbLis]
)
)
WHERE
[SundhedOgOmsorg - Modul].[Modul].&[Hjemmehjælp]
CELL PROPERTIES
VALUE
,BACK_COLOR
,FORE_COLOR
,FORMATTED_VALUE
,FORMAT_STRING
,FONT_NAME
,FONT_SIZE
,FONT_FLAGS;
You could try using one of the following iterative mdx functions:
Generate - https://msdn.microsoft.com/en-us/library/ms145526.aspx
Filter - https://msdn.microsoft.com/en-us/library/ms146037.aspx
To use filter is a little more convoluted as you need to specify specific tuples based on their relative positions. Generate is a little more straightforward. I will try to provide an example against the MS AdvWrks cube.
I think this is relatively similar to your situation:
SELECT
{[Measures].[Internet Sales Amount]} ON 0
,NON EMPTY
[Product].[Product Categories].[Product]
*
{
[Date].[Calendar].[Date].&[20050801]
:
[Date].[Calendar].[Date].&[20050807]
} ON 1
FROM [Adventure Works];
You would like the rows I've marked in red (there are lots of products with only 1 row)
So if we now apply the following multi-dimensional expression to the cube:
WITH
SET [prodSet] AS
[Product].[Product Categories].[Product]
SET [prodDtSet] AS
Generate
(
[prodSet] AS P
,Head
(
P.Current
*
NonEmpty
(
{
[Date].[Calendar].[Date].&[20050801]
:
[Date].[Calendar].[Date].&[20050807]
}
,(
P.Current
,[Measures].[Internet Sales Amount]
)
)
)
)
SELECT
{[Measures].[Internet Sales Amount]} ON 0
,[prodDtSet] ON 1
FROM [Adventure Works];
We get the results required:
Are you able to adapt my example to your context?
I will have a further play and supply a solution using Filter (it'll be, in a way, a little more complicated than the Generate approach)
Here is an approach using Filter:
WITH
SET [prodSet] AS
[Product].[Product Categories].[Product]
SET [prodDtSet] AS
NonEmpty
(
[prodSet]
*
{
[Date].[Calendar].[Date].&[20050801]
:
[Date].[Calendar].[Date].&[20050807]
}
,[Measures].[Internet Sales Amount]
)
SET [prodDtSetFiltered] AS
Filter
(
[prodDtSet]
,
(NOT
[prodDtSet].Item(
[prodDtSet].CurrentOrdinal - 1).Item(0)
IS
[prodDtSet].Item(
[prodDtSet].CurrentOrdinal - 2).Item(0))
OR
[prodDtSet].CurrentOrdinal = 1
)
SELECT
{[Measures].[Internet Sales Amount]} ON 0
,[prodDtSetFiltered] ON 1
FROM [Adventure Works];
Results are as following:
I wanted to do the trend analysis between the dates. For an instance current date- 30 days
30-60 days and so on.Below is the snippet of comparable sql query but same I wanted to do in MDX.
SQL
SELECT
ROUND
(
(
(
(
SELECT
SUM(del_pri_impr)
FROM
reporting.so_sli_calc_val a,
reporting.user_group_tenant b,
reporting.salesorder c
WHERE
created_on BETWEEN DATE(now()-30) AND DATE(now())
)
-
(
SELECT
SUM(del_pri_impr)
FROM
reporting.so_sli_calc_val a,
reporting.user_group_tenant b,
reporting.salesorder c
WHERE
created_on BETWEEN DATE(now()-60) AND DATE(now()-30)
)
)
/
(
SELECT
SUM(del_pri_impr)
FROM
reporting.so_sli_calc_val a,
reporting.user_group_tenant b,
reporting.salesorder c
WHERE
created_on BETWEEN DATE(now()-60) AND DATE(now()-30)
) *100
)
,
0
) AS trend
MDX:
WITH
SET [~FILTER] AS
{[Created_Date.Created_Hir].[Created_On].[2014-04-01]:[Created_Date.Created_Hir].[Created_On].[2014-04-30]}
SET [~ROWS] AS
{[Sales Order Attributes SO.Sales_order].[Sales Order ID].Members}
SELECT
NON EMPTY {[Measures].[CONT_AMT_GROSS], [Measures].[CONT_AMT_NET]} ON COLUMNS,
NON EMPTY [~ROWS] ON ROWS
FROM [SALES_ORDER]
WHERE [~FILTER]
As of now I have hard coded the dates, that will come from parameters.
I am facing difficulty in creating the second set and how to do subtraction between two sets in MDX.
You already have the logic on how to obtain sets of date corresponding to "last 30 days from now" and "last 60 to last 30 days from now". So, I am going to skip that part.
NOTE - You would have to use the parameter values while building these sets.
What you want to do here is first find the values corresponding to these sets of dates and then perform operations on them.
You can proceed like this -
WITH
SET [~FILTER] AS
{[Created_Date.Created_Hir].[Created_On].[2014-04-01]:[Created_Date.Created_Hir].[Created_On].[2014-04-30]}
SET [~ROWS] AS
{[Sales Order Attributes SO.Sales_order].[Sales Order ID].Members}
SET [Last30Days] AS
...
SET [Last60ToLast30Days] AS
...
MEMBER [~Last30Days - Now] AS
Aggregate
(
[Last30Days],
[Measures].[SomeMeasure]
)
MEMBER [~Last60Days - Last30Days] AS
Aggregate
(
[Last60ToLast30Days],
[Measures].[SomeMeasure]
)
MEMBER [~Measure] AS
([~Last30Days - Now]-[~Last60Days - Last30Days] )/([~Last60Days - Last30Days] * 100), format_string = '#,##0'
SELECT
NON EMPTY {
[Measures].[CONT_AMT_GROSS],
[Measures].[CONT_AMT_NET],
[~Measure]
} ON COLUMNS,
NON EMPTY [~ROWS] ON ROWS
FROM [SALES_ORDER]
Format_String takes care of rounding.
Not sure if I totally agree with Sourav's answer as I think some form of aggregation will be needed; creating tuples with sets in them may raise an exception.
Here is a simple model, against AdvWrks, that is tested and will do a subtraction for you:
WITH
SET [Set1] AS
[Date].[Calendar].[Date].&[20060301]
:
[Date].[Calendar].[Date].&[20070308]
SET [Set2] AS
[Date].[Calendar].[Date].&[20070308]
:
[Date].[Calendar].[Date].&[20080315]
MEMBER [Date].[Calendar].[All].[Set1Agg] AS
aggregate([Set1])
MEMBER [Date].[Calendar].[All].[Set2Agg] AS
aggregate([Set2])
MEMBER [Date].[Calendar].[All].[x] AS
(
[Date].[Calendar].[All].[Set1Agg]
,[Measures].[Internet Sales Amount]
)
MEMBER [Date].[Calendar].[All].[y] AS
(
[Date].[Calendar].[All].[Set2Agg]
,[Measures].[Internet Sales Amount]
)
MEMBER [Date].[Calendar].[All].[x-y] AS
[Date].[Calendar].[All].[x] - [Date].[Calendar].[All].[y]
SELECT
{
[Date].[Calendar].[All].[x]
,[Date].[Calendar].[All].[y]
,[Date].[Calendar].[All].[x-y]
} ON 0
,[Product].[Category].[Category] ON 1
FROM [Adventure Works];
Reflecting against your code maybe something like the following:
WITH
SET [Set1] AS
[Created_Date.Created_Hir].[Created_On].[2014-04-01]
:
[Created_Date.Created_Hir].[Created_On].[2014-04-30]
SET [Set2] AS
[Created_Date.Created_Hir].[Created_On].[2014-03-01]
:
[Created_Date.Created_Hir].[Created_On].[2014-03-31]
MEMBER [Created_Date.Created_Hir].[All].[Set1Agg] AS
Aggregate([Set1])
MEMBER [Created_Date.Created_Hir].[All].[Set2Agg] AS
Aggregate([Set2])
MEMBER [Measures].[~Last30Days - Now] AS
(
[Created_Date.Created_Hir].[All].[Set1Agg]
,[Measures].[SomeMeasure]
)
MEMBER [Measures].[~Last60Days - Last30Days] AS
(
[Created_Date.Created_Hir].[All].[Set2Agg]
,[Measures].[SomeMeasure]
)
MEMBER [Measures].[~Measure] AS
([Measures].[~Last30Days - Now] - [Measures].[~Last60Days - Last30Days])
/
[Measures].[~Last60Days - Last30Days]
* 100
,format_string = '#,##0'
SET [~ROWS] AS
{
[Sales Order Attributes SO.Sales_order].[Sales Order ID].MEMBERS
}
SELECT
NON EMPTY
{
[Measures].[CONT_AMT_GROSS]
,[Measures].[CONT_AMT_NET]
,[Measures].[~Measure]
} ON COLUMNS
,NON EMPTY
[~ROWS] ON ROWS
FROM [SALES_ORDER]
WHERE
[~FILTER];
Using the illustrated mockup
(Note not all DimB members show so the total for DimA is larger than the sum of the displayed DimB, ignore this):
Query is showing (months,revenue) on 0, (dima,dimb) on 1 from cube
I would like some assistance in creating the calculated member that would calculate the running total across "Months" here (not a real time dimension).
Earlier i was using this one, but it was wrong on so many levels:
[Measures].[Accumulated Revenue] =
IIF(
([DimMonths].[Months].CurrentMember,[Measures].[Revenue]) = 0
AND ([DimMonths].[Months].CurrentMember.NextMember,[Measures].[Revenue]) = 0
,
IIF(
AGGREGATE({
[DimMonths].[Months].CurrentMember :
[DimMonths].[Months].Parent.LastChild
},[Measures].[Revenue]) = 0
,
NULL
,
Aggregate( {
[DimMonths].[Months].Parent.FirstChild :
[DimMonths].[Months].CurrentMember.PrevMember
}
,[Measures].[Revenue])
)
,
Aggregate( {
[DimMonths].[Months].Parent.FirstChild :
[DimMonths].[Months].CurrentMember
}
,[Measures].[Revenue])
)
Sounds like a job for a "scoped assignment". Basically, using a scoped assignment, you can overwrite the value of your calculated measure along the [Member_DimA_01] slice so that these values represent a running total instead of a sum of children.
Here's a good tutorial from Chris Webb on scoped assignments to help get you started...
Edit: here's a template for the running total calculation...
WITH
SET [Months] AS
{
[Date].[Calendar Month].&[2011 - Jan]
:
[Date].[Calendar Month].&[2011 - Dec]
}
MEMBER [Measures].[Running Total] AS
SUM(
{
[Date].[Calendar Hierarchy].[Calendar Month].&[2011 - Jan]
:
[Date].[Calendar Hierarchy].CurrentMember
}
,[Measures].[Revenue]
)
SELECT
NON EMPTY{
[Months]
} ON 0,
NON EMPTY{
[DimA].[Member].Allmembers *
[DimB].[Member].Allmembers
} ON 1
FROM
[<<cube name>>]
WHERE
[Measures].[Revenue Running Total]
I have created an MDX query which calculates the TOP 10 ZipCodes (according to my Patient Stay measure) as such:
WITH
MEMBER [Discharge Date].[Y-M-D].[ Aggregation] AS 'AGGREGATE( EXISTING { [Current Month] } )', SOLVE_ORDER = 0
SELECT
NON EMPTY { [Measures].[Patient Stays] }
ON COLUMNS,
TOPCOUNT({ ORDER( HIERARCHIZE( { [Patient].[ByZipcode].[All].CHILDREN } ), ( [Measures].[Patient Stays] ), BDESC ) }, 10)
ON ROWS
FROM [Patient Stay]
WHERE ( [Discharge Date].[Y-M-D].[ Aggregation], [Facility].[ByAffiliation].CURRENTMEMBER, [Facility].[ByRegion].CURRENTMEMBER )
This query is used to populate a PerformancePoint 100% Stacked Bar chart. The client has asked that since this is a !00% based chart, we lump the rest of the zip codes into an "Other" field, such that there should be 11 values: one for each of the top 10, and an eleventh which is a sum of the remaining Zip Codes.
I am an extreme novice to MDX, but this doesn't souund like it should be impossible. Does anyone have any ideas or suggestions?
I'll do my best with untested code, so here goes:
WITH
MEMBER [Discharge Date].[Y-M-D].[ Aggregation] AS 'AGGREGATE( EXISTING { [Current Month] } )', SOLVE_ORDER = 0
SET [Top10ZipCodes] AS
(TOPCOUNT({ ORDER( HIERARCHIZE( { [Patient].[ByZipcode].[All].CHILDREN } ), ( [Measures].[Patient Stays] ), BDESC ) }, 10))
MEMBER [Patient].[ByZipCode].[OtherZipCodes] AS
(AGGREGATE({EXCEPT([Patient].[ByZipCode].Members, [Patient].[ByZipCode].[Top10ZipCodes])}))
SELECT
NON EMPTY { [Measures].[Patient Stays] }
ON COLUMNS,
{[Top10ZipCodes], [Patient].[ByZipCode].[OtherZipCodes]}
ON ROWS
FROM [Patient Stay]
WHERE ( [Discharge Date].[Y-M-D].[ Aggregation], [Facility].[ByAffiliation].CURRENTMEMBER, [Facility].[ByRegion].CURRENTMEMBER )
What this does is creates a set of your top 10 ZIP codes, and then aggregates (different than sum!!!) all the ZIP codes, with the exception of your top 10.
Also, if this is a common set (top 10 ZIP codes), you may want to make a set on the cube, where you can reuse it ad nauseum, without having to change every MDX query you have.
Cheers,
Eric