MDX calculated member for average sales for top 10 persons - ssas

Supposing I have an electronics store with 10 types of articles and 50 sales persons. What can I do to get the average number of sold articles for the 10 persons with more sales for each type of article?
I started creating named sets for the top 10 persons for each article:
CREATE DYNAMIC SET CURRENTCUBE.[Top 10 Persons - Laptops]
AS TopCount([Dim Person].[Person Name].Members, 10, ([Measures].[Sales], [Dim Article].[Article Name].&[Laptop]));
CREATE DYNAMIC SET CURRENTCUBE.[Top 10 Persons - TVs]
AS TopCount([Dim Person].[Person Name].Members, 10, ([Measures].[Sales], [Dim Article].[Article Name].&[TV]));
I would do this for the other eight.
Then I was trying to create a calculated member for each article type. Each calculated member would sum the total sales for a particular article for the top 10 persons included in the corresponding named set, and then just divide that by 10.
How can I do this? Or, would you recommend a different approach?

I was able to find a solution to this. It is not necessary to create the named set. This is what I ended up doing:
Avg(TopCount([Dim Person].[Person Name].Children, 10, ([Measures].[Sales], [Dim Article].[Article Name].&[Laptop])), ([Measures].[Sales], [Dim Article].[Article Name].&[Laptop]))

Related

MDX - Top N elements of every subgroup

Let's assume I have a cube with a sales fact table and 3 dimensions: Time (with hierarchy year-month-day), Geography (with hierarchy continent-country-region) and Product with some characteristics about the product sold, let's take the brand for instance.
What I am trying to do is to display the top N brands with respect to the measure chosen, in this case average sales (which is already in the cube as total sales/number of products sold), for every region and month.
I also need to display the country and the year, for clearness.
I have searched for the solution to this everywhere, I came close to it but not completely. I hope someone can help me figure it out.
So I used generate and topcount with the following query, but the problem is that the topcount calculates the N best selling brands over the whole dataset, not for every region and month subgroup. And then applies this top N to every subgroup.
WITH SET [Top N Brands] AS
Generate([Geography].[Region].Children,
TopCount(Geography].[Region].CurrentMember * [Gpu Product].[Brand].[Brand].MEMBERS,
5, ([Measures].[averageSales])))
SELECT {[Measures].[averageSales]} ON COLUMNS,
NON EMPTY ( [Time].[Year].[Year],
[Time].[Month].[Month],
[Geography].[Country].[Country],
[Top N Brands]) ON ROWS
FROM [Cube]
So I am getting this, with the global top 5 brands distributed over the regions, if sold there:
But I should get this with different top 5s for every region:
What am I missing?
You need to use rank. Take a look at the example below. I am using the sample Adventure Works Db, here I am listing For each country, for each product category in that country, the top three subcategories according to internet sales.
WITH
MEMBER [Measures].[Internet Sales Amount Rank] AS
RANK( ([Customer].[Country].currentmember,[Product].[Category].currentmember,[Product].[Subcategory].CurrentMember),
ORDER( ([Customer].[Country].currentmember,[Product].[Category].currentmember,[Product].[Subcategory].[Subcategory].Members) , [Measures].[Internet Sales Amount], BDESC)
)
select
non empty
([Measures].[Internet Sales Amount])
on columns
,
non empty
([Customer].[Country].[Country],
[Product].[Category].[Category],
filter([Product].[Subcategory].[Subcategory],[Measures].[Internet Sales Amount Rank]<4))
on rows
from [Adventure Works]
Result

Create Calculate Measure Based On One Dimension And 2 Relations In SSAS

Please Consider this Fact Table:
Sender Receiver Amount
----------------------------------------
Reseller1 Resseler2 100
Reseller1 Resseler3 200
Reseller3 Resseler1 150
Reseller3 Resseler2 50
Reseller1 Resseler4 100
Reseller4 Resseler2 350
Reseller4 Resseler1 500
Reseller4 Resseler3 250
I want create a calculate Measures based on this formula: Sum(Receiver)-Sum(Sender) and create such this result:
Reseller Amount
---------------------------
Reseller1 250 <---- (500 + 150) - (100 + 200 + 100)
Reseller2 500 <---- (100 + 50 + 350) - (0)
Reseller3 250 <---- (200 + 250) - (150 + 50)
Reseller4 -1000 <---- (100) - (350 + 500 + 250)
How can I create calculate measure for this?
Thanks
My DimReseller is:
ResellerCode ResellerName
---------------------------------------
1 Reseller1
2 Reseller2
3 Reseller3
4 Reseller4
and it has two relationship with Sender and Receiver
Edit 1)
Based on Master #Saeid Yousefi's answer:
My structure is:
I wrote this MDX query:
WITH
MEMBER SenderAmount AS
[Measures].[Amount], FORMAT_STRING = "Standard"
MEMBER ReceiverAmount AS
(LinkMember
([Sender].[Hierarchy].CurrentMember, [Receiver].[Hierarchy])
,[Measures].[Amount]), FORMAT_STRING = "Standard"
MEMBER DiffAmount AS
ReceiverAmount - SenderAmount, FORMAT_STRING = "Standard"
SELECT {SenderAmount, ReceiverAmount, DiffAmount} ON 0,
[Sender].[Hierarchy].MEMBERS ON 1
FROM [Reseller Sales]
but I got null for receiver amount:
I know there is a small problem but I can't fix that!
Sample approach to your task:
In DSV - create two tables (as SQL named queries) with Sender - Amount and Receiver - Amount columns. Thus you effectively split Sellers and Receivers data.
On Cube - create two measure groups with Sum aggregation on Amount column and linked to DimReseller dim.
Create a Calc measure as [Measures].[Receiver Amount] - [Measures].[Sender Amount]
Sometimes in a data warehouse a dimension is connected to a fact table in more than one way, these ways can be created using direct or indirect links between Dim and Fact, therefore we can use a dimension to analyze Fact values in different roles; these dimensions are called Role-Playing Dimensions.
When designing a cube, for each role of the dimension, a new instance of dimension will be added to the cube.
Given these circumstances, each dimension will analyze the cube and although you can use multiple dimensions in a report but in Members level these dimensions are distinguished. With these said, sometimes we feel the need to select a member to be the representative of all roles of a dimension given the situation, this is when Link Member function jumps in to aid us.
This function takes two arguments:
Member Expression: An MDX expression which returns a member.
Hierarchy Expression: An MDX expression which returns a hierarchy.
This function returns the member equivalent to a specified member in a specified hierarchy.
So, your code should be something like following:
WITH
MEMBER SenderAmount AS
[Measures].[Amount], FORMAT_STRING = "Standard"
MEMBER ReceiverAmount AS
(LinkMember
([Sender].[Hierarchy].CurrentMember, [Receiver].[Hierarchy])
,[Measures].[Amount]
,[Sender].[Hierarchy].[All]), FORMAT_STRING = "Standard"
MEMBER DiffAmount AS
ReceiverAmount - SenderAmount, FORMAT_STRING = "Standard"
SELECT {SenderAmount, ReceiverAmount, DiffAmount} ON 0,
NON EMPTY [Sender].[Hierarchy].MEMBERS ON 1
FROM [Cube]
Please pay attention to LinkMember function which is working on role-playing dimensions. So, [Sender] and [Receiver] are the names of your dimensions which are attached to your cube, you can find the name of those in Dimension Usage tab of your cube. Also, [Hierarchy] is the name of your attribute or standard hierarchy, so according to the screenshot of your dimension configuration, it should be [Dimension Name] + either [Hierarchy].[Reseller Code].members or [Reseller Code].members or [Hierarchy].members depending on what you want.

Common calculated measure across all dimensions

I have a cube with 4 dimensions and I have a measure called Transaction Count. Now I want to calculate the Percentage across all the dimensions for that above measure.
I also have a dimension called Cars. I have the count across all the Cars and now I have defined a calculated measure for calculating the Percentage of each car from the total number of transactions. But it will work only for that particular dimension.
How I can create a single percentage calculated measure which can be used across all the dimensions?
MDX for the calculated measure: (which is working for only Carmake dimension)
CASE
WHEN ISEMPTY( [MEASURES].[Trans COUNT] )
THEN 0
ELSE ([Dim Car Make].[Hierarchy].CURRENTMEMBER,
[MEASURES].[FACT COLORPERFORMANCE COUNT])/
( [DIM CAR MAKE].[CARMAKE].[(ALL)].[ALL],
[MEASURES].[Trans COUNT])
END
I already have a Trancount(1000) measure. Now I need to create a calculated measure Freq % which should be calculated across all the dimensions.
Screenshot -> http://i.stack.imgur.com/iuaQO.jpg (need 10 rep for posting images)
Table 1 in screenshot - you drag and drop the carmake dimension, then both Tran Count and Freq% should be calculated as per CarMake breakdown.
Table 2 in screenshot - you remove CarMake and drag Quality, then both Tran Count and Freq% should be calculated as per Quality breakdown.
Table 3 in screenshot - you remove Quality and drag Brand, then both Tran Count and Freq% should be calculated as per brand breakdown.
The best way i found is using AXIS() to dynamically get the currently used dimension.
with
member Member_Lvl as AXIS(0).item(0).level.ordinal --get the level for next calc
member All_Member as sum(ancestor(axis(0).item(0).hierarchy.currentMember,<yourMeasure>),Member_Lvl )
member Percent_of_All as sum(axis(0).item(0).hierarchy.currentMember,<yourMeasure>) / All_Member
select <Your Dim > on 0, {<Your Measure>, Percent_of_All} on 1
from <Your Cueb>
NOTICE: replace the SUM function on the calculations if you need other aggregation.

SSAS MDX query, Filter rows by sales people

I am learning how to query Cubes using MDX (SQL Server 2012) queries. I have been presented with a challenge. We have a hierarchy of sales people, a stored procedure returns a table with all sales people working under a manager. I have a classic sales cube where FactSales PK is invoice number and invoice line and a dimension for all our Sales people.
How can I filter the invoices where the sales person is in a table ?
Something like this but translated to MDX:
select * from sales where SalesPerson in (select SalesPerson from #salespeople)
The only way I see this could work is by writing the query dynamically and adding each salesperson in a filter, but that is not optimal in my opinion, we can have 200 or 400 people that we want to return sales from.
thanks!
If the dimension containing the sales people contains the hierarchy (who works for whom), you can resolve the challenge without using the stored procedure. Let's say your manager is named "John Doe" and your sales person hierarchy is named [Sales Person].[Sales Person]. Then just use
[Sales Person].[Sales Person].[John Doe].Children
in your query if you want to see sales for the people working directly for John, and you are done. In case you want to see John himself and everybody working for him directly or indirectly, you would use the Descendants function as follows:
Descendants([Sales Person].[Sales Person].[John Doe], 0, SELF_AND_AFTER)
This function has many variants, documented here.
In the Microsoft sample Adventure Works cube, where a similar hierarchy is called [Employee].[Employees], you could run the following query:
SELECT {
[Measures].[Reseller Sales Amount]
}
*
[Date].[Calendar].[Calendar Year].Members
ON COLUMNS,
Descendants([Employee].[Employees].[Jean E. Trenary], 0, SELF_AND_AFTER)
ON ROWS
FROM [Adventure Works]
to see the sales of employees working directly or indirectly for "Jean E. Trenary".

In MDX how can I filter a dimension/axis based on a TopCount

I have cube which contains geographic sales data. I want to pull sales of product items from all stores, based on the top 5 sellers from an arbitrary known store (BTW this is a simplified version of the real issue).
In sql (shame on me) this would be
select StoreId, ProductId, Sales from cube where ProductId in
(select top 5 ProductId from cube where Store = #Store order by Sales desc)
You can use the Topcount function for this. Provided you have dimensions named Product and Store and a measure named [Sales]:
Select [Measures].[Sales] On Columns,
CrossJoin([Store].Members,Generate(Topcount(Crossjoin({[Store].#[<StoreId>]},[Product].Members),5,[Measures].[Sales]),[Product].CurrentMember)) On Rows
From [Yourcube]
Replace <StoreId> with the specific store you're interested in. Generate will loop through the top 5 found for the specific store and return only the Product members. This result is then crossjoined with all the stores.
This will extract the top 5 products for your-store in ROWS axis and then select the [Sales] of these products according to the defaultMember of the [Store] dimension. In case [Store] defaultMember is the root of an aggregatable hierarchy this should give the sales of each product over all the stores.
SELECT
[Measures].[Sales] ON 0,
TopCount( [Store].[your-store] * [Product].Members ), 5, [Measures].[Sales] ) ON 1
FROM [your-cube]