I am not an MDX expert, I have this simplified query:
WITH MEMBER [Measures].[SalesCalc] AS
(
[Time Calculations].[Aggregation].&[4]
,[Measures].[Sales]
)
SELECT
[Measures].[SalesCalc]
ON 0
,{
[Product].[Product Source].[Product Source] - [Product].[Product Source].&[2]
} ON 1
FROM [Cube]
Which calculates my measure (from existing measure and pre-calculated aggregation) and shows all product sources except one particular source.
My goal is to show all the sources, the &[2] source should be there but the measure value for it should be NULL.
So I'm trying to get something like:
WITH MEMBER [Measures].[SalesCalc] AS
(
[Time Calculations].[Aggregation].&[4]
,[Measures].[Sales]
)
SELECT
[Measures].[SalesCalc] //but for [Product].[Product Source].&[2] this is NULL
ON 0
,
[Product].[Product Source].[Product Source] ON 1
FROM [Cube]
I seem to be unable to add the "do not calculate for product source &[2]" in measure and I cannot use the product source hierarchy on rows when I do a select since its already used on columns.
Any ideas?
Maybe try using IIF
WITH
MEMBER [Measures].[SalesCalc] AS
IIF(
[Product].[Product Source].CURRENTMEMBER
IS [Product].[Product Source].[Product Source].&[2]
,NULL
(
[Time Calculations].[Aggregation].&[4]
,[Measures].[Sales]
)
)
SELECT
[Measures].[SalesCalc] ON 0
,[Product].[Product Source].[Product Source] ON 1
FROM [Cube];
Related
I have an existing SSRS report out of T-SQL query and I am trying to recreate it using MDX queries on SSAS cube. I am stuck with rewriting Row num and rank logic to MDX.
It is written as:
SELECT ceil((ROW_NUMBER() OVER (PARTITION BY PRODUCT ORDER BY YEARMONTH))/12)
Rank1 in the SQL. Can someone tell me if this can be done using MDX? In the cube, PRODUCT and YEARMONTH are coming from separate dimensions.
Thank you for your help!
There is the Rank() function. For example:
with
Dynamic Set OrderedSet as
Order(
NonEmptyCrossJoin(
[Date].[Year].[Year].Members,
[Product].[Product].[Product].Members,
[Measures].[Invoice Count],
2
),
[Measures].[Invoice Count],
BDESC
)
Member [Measures].[Rank] as
Rank(
([Client].[Client].Currentmember,[Date].[Year].CurrentMember),
OrderedSet
)
select {[Measures].[Invoice Count],[Measures].[Rank]} on 0,
non empty OrderedSet on 1
from [BI Fake]
where ([Date].[Day].&[20160120])
You can read in details about it from my blog post.
You can use Generate to repeat ranks like this:
WITH
SET [SalesRank] AS
Generate
(
[Customer].[Customer Geography].[State-Province]
,Order
(
NonEmpty
(
(
[Customer].[Customer Geography].CurrentMember
,[Product].[Product Categories].[Subcategory]
)
,{[Measures].[Internet Sales Amount]}
)
,[Measures].[Internet Sales Amount]
,BDESC
)
)
MEMBER [Measures].[CategoryRank] AS
Rank
(
(
[Customer].[Customer Geography].CurrentMember
,[Product].[Product Categories].CurrentMember
)
,Exists
(
[SalesRank]
,[Product].[Product Categories].CurrentMember
)
)
SELECT
{
[Measures].[Internet Sales Amount]
,[Measures].[CategoryRank]
} ON 0
,[SalesRank] ON 1
FROM [Adventure Works];
It results in this:
Subselects only support the COLUMNS axis.
SELECT NON EMPTY { [Measures].[Total Due] } ON COLUMNS,
TopCount ({[Store].[Name].Members *[Customer].[Store ID 1].Members }
,5,
[Measures].[Total Due]) ON ROWS
FROM [TOP_5]
Subselects support as many axes as you like - in fact the subselect is one of the occasions where you can practically use more than two axes.
SELECT
[Sales Territory].[Sales Territory Region].MEMBERS ON 0
,[Date].[Calendar].[Calendar Year].MEMBERS ON 1
FROM
( //<< subselect starts here
SELECT
[Sales Territory].[Sales Territory Region].[Canada] ON 0
,[Product].[Product].[Mountain-200 Black, 42] ON 1
,[Promotion].[Promotion Type].[No Discount] ON 2
,[Date].[Calendar].[Calendar Year].[CY 2008] ON 3
FROM [Adventure Works]
) //<< subselect ends here
WHERE
[Measures].[Sales Amount];
Did you try the WITH clause
WITH SET [X] AS
TopCount (
{[Store].[Name].Members *[Customer].[Store ID 1].Members }
,5
,[Measures].[Total Due]
)
SELECT
NON EMPTY { [Measures].[Total Due] } ON COLUMNS,
[X] ON ROWS
FROM [TOP_5];
I have my mdx query:
SELECT
NON EMPTY
{[Measures].[Amount]} ON COLUMNS
,NON EMPTY
{[Dim Date].[Day Of Week].[Day Of Week].MEMBERS} ON ROWS
FROM
(
SELECT
[Dim Date].[Date Int].&[20140730] : [Dim Date].[Date Int].&[20150730] ON COLUMNS
FROM [Cube]
WHERE
[Dim Client].[Common Client UID].&[{some id}]
);
so i have my a weekday dim, which contain members as numbers from 1-7. Query find returns amount for each weekday, which is summed up, but i want to find out an average, so somehow i need to find out how many items was summed to give me [Measures].[Amount] result. I have tryed with separate member function which didnt worked.
WITH MEMBER [Measures].[Avg] AS
Avg(
( [Dim Date].[Day Of Week].CURRENTMEMBER, [Measures].[Amount] )
)
Avg return exectly the same value. How do i do such a request in mdx?
This will give you an average over 1 member:
WITH MEMBER [Measures].[Avg] AS
Avg(
( [Dim Date].[Day Of Week].CURRENTMEMBER, [Measures].[Amount] )
)
That is because CURRENTMEMBER is returning 1 member.
If you want an average over several members than you need to supply a set as the first argument for the Avg function. Here is an example:
WITH MEMBER [Measures].[Daily Avg] AS
Avg(
Descedants(
[Date].[Date - Calendar Month].CURRENTMEMBER
,[Date].[Date - Calendar Month].[Calendar Day]
,[Measures].[Amount]
)
Although I suspect something like the follwoing should work in your context:
WITH
MEMBER [Measures].[Avg] AS
Avg
(
(EXISTING
[Dim Date].[Date Int].MEMBERS)
,[Measures].[Amount]
)
SELECT
NON EMPTY
{
[Measures].[Amount]
,[Measures].[Avg]
} ON COLUMNS
,NON EMPTY
{[Dim Date].[Day Of Week].[Day Of Week].MEMBERS} ON ROWS
FROM
(
SELECT
[Dim Date].[Date Int].&[20140730] : [Dim Date].[Date Int].&[20150730] ON COLUMNS
FROM [Cube]
WHERE
[Dim Client].[Common Client UID].&[{some id}]
);
How do I get the sales for the last product of a cross join of each product group and brand? I had a look at the Tail function but I can't get it to work properly.
This is the MDX I have so far:
SELECT {[Measures].[Sales Amount]} ON COLUMNS,
{
[Dim Brands].[Brand Name].[Brand Name].ALLMEMBERS *
[Dim Product Groups].[Product Group Name].[Product Group Name].ALLMEMBERS *
Tail ([Dim Products].[Product Name].[Product Name].ALLMEMBERS)
}
It only returns the last product for the whole cube rather than the last product for each brand and product group.
You can use the GENERATE function to generate the product for every combo or Brand and product group. The EXISTING takes care of the scope.
WITH SET LastProductForEachBrandAndProductGroup AS
GENERATE
(
EXISTING
NonEmpty
(
[Dim Brands].[Brand Name].[Brand Name].ALLMEMBERS, [Dim Product Groups].[Product Group Name].[Product Group Name].ALLMEMBERS
)
,
Tail (
[Dim Products].[Product Name].[Product Name].ALLMEMBERS
)
)
SELECT {[Measures].[Sales Amount]} ON COLUMNS,
NonEmpty({
[Dim Brands].[Brand Name].[Brand Name].ALLMEMBERS *
[Dim Product Groups].[Product Group Name].[Product Group Name].ALLMEMBERS *
LastProductForEachBrandAndProductGroup
}) ON ROWS
FROM YourCube
If by last, you imply the last member in any sorted(by some measure) list, the above would need some more work. Let me know how it works out for you.
Separating out the sets should speed this script up. Like the following:
WITH
SET [allBrands] AS
[Dim Brands].[Brand Name].[Brand Name].ALLMEMBERS
SET [allGroups] AS
[Dim Product Groups].[Product Group Name].[Product Group Name].ALLMEMBERS
SET [A] AS
Generate
(
{[allBrands] * [allGroups]} AS s
,
s.Current
*
Tail
(
NonEmpty
(
[Dim Products].[Product Name].[Product Name].ALLMEMBERS
,[Measures].[Sales Amount]
)
,1
)
)
SELECT
NON EMPTY
{[Measures].[Sales Amount]} ON 0
,NON EMPTY
[A] ON 1
FROM [YourCube];
Against Microsoft's AdvWrks a similar, and maybe more useful, variant of the above would be to use TopCount rather than the slightly artitrary Tail:
WITH
SET [allYears] AS
[Date].[Calendar].[Calendar Year].MEMBERS
SET [allCountries] AS
[Customer].[Customer Geography].[Country].MEMBERS
SET [A] AS
Generate
(
{[allYears] * [allCountries]} AS s
,
s.Current
*
TopCount
(
[Product].[Product Categories].[Product].ALLMEMBERS
,2
,[Measures].[Internet Sales Amount]
)
)
SELECT
{[Measures].[Internet Sales Amount]} ON 0
,[A] ON 1
FROM [Adventure Works];
This results in the following:
I've below MDX query which gives me YTD amount for each my device perfectly, but I want count of those YTD days taken in consideration while calculating YTD amount.
How can I achieve those YTD days counts in my query?
WITH
MEMBER [Settlement Date].[Calendar].[CalendarYTD] AS
Aggregate
(
YTD
(
[Settlement Date].[Calendar].[Settlement Calendar Month].&[201412]
)
)
SELECT
[Settlement Date].[Calendar].[CalendarYTD] ON COLUMNS
,NON EMPTY
[Device].[DeviceID].Children ON ROWS
FROM [cube1]
WHERE
[Measures].[amount];
OR
you can use below AW MDX query while making changes which give same results as my above query:
WITH
MEMBER [Date].[Calendar].[CalendarYTD] AS
Aggregate(YTD([Date].[Calendar].[Month].[March 2015]))
SELECT
[Date].[Calendar].[CalendarYTD] ON COLUMNS
,[Product].[Category].Children ON ROWS
FROM [Adventure Works]
WHERE
[Measures].[Order Quantity];
this is a little swapped around but hopefully heading in the direction you require:
WITH
MEMBER [Date].[Calendar].[CalendarYTD] AS
Aggregate(YTD([Date].[Calendar].[Month].[March 2007]))
MEMBER [Measures].[DaysCompleteCurrYear] AS
Descendants
(
YTD([Date].[Calendar].[Month].[March 2007])
,[Date].[Calendar].[Date]
,SELF
).Count
SELECT
{
[Measures].[DaysCompleteCurrYear]
,[Measures].[Order Quantity]
} ON COLUMNS
,[Product].[Category].Children ON ROWS
FROM [Adventure Works]
WHERE
[Date].[Calendar].[CalendarYTD];
If we put the target month into a single member set then the family relationships are preserved and we can use that set in the custom measures:
WITH
SET [targMth] AS
{[Date].[Calendar].[Month].[March 2007]}
MEMBER [Date].[Calendar].[CalendarYTD] AS
Aggregate(YTD([targMth].Item(0).Item(0)))
MEMBER [Measures].[DaysCompleteCurrYear] AS
Descendants
(
YTD([targMth].Item(0).Item(0))
,[Date].[Calendar].[Date]
,SELF
).Count
SELECT
{
[Measures].[DaysCompleteCurrYear]
,[Measures].[Order Quantity]
} ON COLUMNS
,[Product].[Category].Children ON ROWS
FROM [Adventure Works]
WHERE
[Date].[Calendar].[CalendarYTD];