Grouping SSAS members into buckets using MDX - ssas

SSAS and MDX newbie here.
If I have an SSAS cube with Geography, Product as the dimensions and total sales as a measure.
The following elements are under geography:
EAST
WEST
NORTH
SOUTH
MID-ATLANTIC
MOUNTAIN
NORTH-WEST
Products are:
1
2
3
4
For Product ID = 1, is there a way I can group some members into a "rest of the country" bucket and aggregate the sales?
Meaning, the expected output is:
Product ID Geography Sales
1 East 100
1 West 200
1 North 300
1 South 400
1 RestOfNation 1200
2 East 100
2 West 50
2 RestOfNation 1500
Is there a way I can buck some members into "RestOfNation" using an MDX query?

You could try something like this.
Create a named set made up of the members that you'd like to throw into the bucket RestOfWorld.
Make a member, within the geography dimension, that is the aggregation of the rest of world members.
Find the countries that are not in the rest of the world set.
Here is a script against AdvWrks (worth installing as it is a common prototyping tool when playing with mdx and posting to forums):
WITH
SET [RestOfWorld] AS
{
[Customer].[Customer Geography].[Country].&[United Kingdom]
,[Customer].[Customer Geography].[Country].&[Germany]
}
MEMBER [Customer].[Customer Geography].[All].[RestOfWorld] AS
Aggregate
(
{
[Customer].[Customer Geography].[Country].&[United Kingdom]
,[Customer].[Customer Geography].[Country].&[Germany]
}
)
SET [CountriesMinusROW] AS
[Customer].[Customer Geography].[Country].MEMBERS - [RestOfWorld]
SELECT
NON EMPTY
{[Measures].[Internet Sales Amount]} ON 0
,NON EMPTY
[Product].[Category].[Category]
*
{
[CountriesMinusROW]
,[Customer].[Customer Geography].[All].[RestOfWorld]
} ON 1
FROM [Adventure Works]
WHERE
[Date].[Calendar Year].&[2007];
The above gives the following cellset:

Related

Get All Linked Members using LinkMember function

Please consider this structure:
Fact:
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
DimReseller:
ResellerCode ResellerName
---------------------------------------
1 Reseller1
2 Reseller2
3 Reseller3
4 Reseller4
DimReseller is role-playing dimension and has 2 relation with fact table:
Now I wrote this MDX query to select How much money the resellers have paid each other:
WITH MEMBER SenderAmount AS
[Measures].[Amount], FORMAT_STRING = "Standard"
SELECT {SenderAmount} ON 0,
NON EMPTY [Sender].[Hierarchy].MEMBERS ON 1
FROM [MyCube]
and I get this result:
Now I want to get how much money the resellers have received from each other and I wrote this query:
WITH
MEMBER SenderAmount AS
[Measures].[Amount], FORMAT_STRING = "Standard"
MEMBER ReceiverAmount AS
(LinkMember
([Sender].[Hierarchy].CurrentMember, [Receiver].[Hierarchy])
,[Measures].[Amount]), FORMAT_STRING = "Standard"
SELECT {SenderAmount, ReceiverAmount} ON 0,
NON EMPTY [Sender].[Hierarchy].MEMBERS ON 1
FROM [MyCube]
and get this result:
I got null for receive amount. I test this MDX query:
select {LinkMember([Sender].[Hierarchy].[Reseller Code].&[1], [Receiver].[Hierarchy])} on 0
from [MyCube]
and I get 650 (the correct amount) for Reseller1 .Now when I change the query this way:
select {LinkMember([Sender].[Hierarchy].currentmember, [Receiver].[Hierarchy])} on 0,
[sender].[Hierarchy].members on 1
from [MyCube]
I get this result(Again for paid):
and when I change the query this way:
select {LinkMember([Sender].[Hierarchy].currentmember, [Receiver].[Hierarchy])} on 0,
[receiver].[Hierarchy].members on 1
from [MyCube]
I got this error:
The Hierarchy hierarchy already appears in the Axis0 axis.
How can I get this result?
Reseller Received Paind
--------------------------------------------------------
Reseller1 650 400
Reseller2 500 (null)
Reseller3 450 200
Reseller4 100 1100
Sorry for too much explanation...
Thanks
Try the following change:
MEMBER ReceiverAmount AS
(LinkMember
([Sender].[Hierarchy].CurrentMember, [Receiver].[Hierarchy])
,[Measures].[Amount]
,[Sender].[Hierarchy].[All]), FORMAT_STRING = "Standard"

MDX NonEmptyCrossJoin not returning expected results

I am trying to use NonEmptyCrossJoin combined with Extract to return only Members of a given dimension that are relevant. However NonEmptyCrossJoin is not returning the Non Empty tuples.
The following query returns data for the shown EOCs and Index 2.
SELECT
{ [Measures].[MTD BCWP] } ON 0,
{ CROSSJOIN([EOC].[EOC].[EOC], { [INDEX].[INDEX ID].&[2] } ) } ON 1
FROM Metrics
| | MTD BCWP
| 2 | (null)
G | 2 | 939482.280
L | 2 | 7508780.49
M | 2 | 650
O | 2 | 151652.62
Unknown | 2 | (null)
The same query using NonEmptyCrossJoin returns an empty set.
SELECT
{ [Measures].[MTD BCWP] } ON 0,
{ NONEMPTYCROSSJOIN([EOC].[EOC].[EOC], { [INDEX].[INDEX ID].&[2] } ) } ON 1
FROM Metrics
The full query that this is being used in, is much more complicated, but these examples show the crux of the issue. I believe the problem is Dimension or Measure Group configuration related, but don't know what to look for.
The EOC dimension contains only the EOC member.
The Index dimension contains Index Id(PK) and other attributes.
The Measure group includes both Index Id and EOC members that are related to their respective dimensions in addition to other values.
Thank you for your time.
You need to put your crossjoin within a nonempty() and provide the relevant measure to non-empty. The Following example will help
select
{
[Measures].[Internet Sales Amount]
}
on columns,
{
crossjoin([Product].[Subcategory].[Subcategory],{[Geography].[Country].&[United States]})
}
on rows
from
[Adventure Works]
//this results to
Now we modify our query
select
{
[Measures].[Internet Sales Amount]
}
on columns,
{
nonempty(
crossjoin([Product].[Subcategory].[Subcategory],{[Geography].[Country].&[United States]})
,
[Measures].[Internet Sales Amount])
}
on rows
from
[Adventure Works]
//This results to

MDX/SSAS sum of certain values over totals - calculate success/failure rate

I have a simplified example cube used for learning purposes, and to try to figure out a more complex problem.
The cube represents a small web server log,
number of hits as a measure
hostname as a dimension
http status code as a dimension
I can get a breakdown on number of hits per host and http status code with the MDX
SELECT NON EMPTY { [Measures].[CNT HITS] } ON COLUMNS,
NON EMPTY { ([DIM NOS STATUSCODE].[Statuscode].[Statuscode].ALLMEMBERS *
[DIM NOS HOST].[HOST].[HOST].ALLMEMBERS ) } ON ROWS
FROM [DW]
Now what I would like is to make groups over various HTTP status codes to e.g. show the percentage of successful hits (all 2xx status codes), the percentage unsuccessful hits (all non 2xx status codes).
I can do this with SQL, but I'm at a loss on how to do it with MDX. e.g. with SQL I'd do:
select HOST,
sum(CNT_HITS) as HITS ,
SUM(CASE WHEN s.statuscode div 100 = 2 THEN CNT_HITS ELSE 0 END)/sum(CNT_HITS) * 100 as success_percent,
SUM(CASE WHEN s.statuscode div 100 = 2 THEN 0 ELSE CNT_HITS END)/sum(CNT_HITS) * 100 as failed_percent,
sum(CASE WHEN s.statuscode = 401 THEN CNT_HITS ELSE 0 END)/sum(CNT_HITS) * 100 as auth_fail_percent
from FACT_NOS_HTTPLOG fact
group by HOST;
And for the data shown in the above screenshot, I'd get
+-----------------+------+-----------------+----------------+-------------------+
| HOST | HITS | success_percent | failed_percent | auth_fail_percent |
+-----------------+------+-----------------+----------------+-------------------+
| www.example.com | 1610 | 93.1677 | 6.8323 | 6.2112 |
| www.test.com | 50 | 0.0000 | 100.0000 | 0.0000 |
+-----------------+------+-----------------+----------------+-------------------+
But how can I accomplish this with MDX ?
I think the easiest way to accomplish this is to add a column to your fact table (or view/query) that would contain keys for either success_percent, failed_percent or auth_fail_percent. Then create a new dimension with these 3 members. Join to the fact and you have your solution without the need for any MDX at all.
Add an extra attribute [Status] to your [DIM NOS STATUSCODE] dimension and use MDX for percentage, like this:
([DIM NOS STATUSCODE].[Status].&[Failed],[Measures].[CNT HITS]) / [Measures].[CNT HITS]
It will involve a certain amount of hard coding - although you could add these measures into your cube script.
WITH
MEMBER [Measures].[failed_percent] AS
DIVIDE(
(
[DIM NOS STATUSCODE].[Status].&[Failed]
,[DIM NOS HOST].[HOST].currentmember
,[Measures].[CNT HITS]
)
, (
[DIM NOS STATUSCODE].[Status].[All]
,[DIM NOS HOST].[HOST].currentmember
,[Measures].[CNT HITS]
)
)
SELECT
NON EMPTY
{
[Measures].[CNT HITS]
,[Measures].[failed_percent]
} ON COLUMNS,
NON EMPTY
[DIM NOS HOST].[HOST].[HOST].ALLMEMBERS
ON ROWS
FROM [DW];

MDX query and calculated members for two different averages in same query

I have an MDX/calculated member question here. It has been a while since I've done this and have forgotten a lot. I have a cube with the following dimensions and levels:
Sites
Site Name
Clients
Client Name
Industry Name
I have a measure
Product Count
What I want to show/return from an MDX query is the following:
Site | Prod Count | Avg Prod Count Across All Sites for Current Client | Avg Prod Count
Across All Sites in Current Client's Industry
Example Data:
Site | Prod Count | Avg 1 | Avg 2
Site 1 | 100 | 50 | 200
Site 2 | 125 | 50 | 200
Site 3 | 112 | 50 | 200
What I'm trying to figure out is how or if I can use 2 different calculated members to calculate the averages above.
The challenge is that the query has to be in the following format because I'm using a reporting tool and it is generating the MDX.
`SELECT
{
[Measures].[Product Count],
[Measures].[Calc Avg 1],
[Measures].[Calc Avg 2]
} ON COLUMNS,
{[Sites].[Site Name].[Site Name].Members} ON ROWS
FROM [Cube]
where ([Clients].[Client Name].&[Client A])`
So basically, my question is:
What would be the proper way to define the averages I'm looking for using calculated members?
Whenever I try it out I'm only able to calculate the average product count across all sites for the current client, but I'm not able to get the average across all sites in the current client's industry.
here's an example using adventure works to get you started. the calculated members will need to be ported to the MDX script to use with your tool. Here's the mapping:
City = "Client Site"
State = "Client"
Country = "Client Industry"
WITH
MEMBER Measures.ClientCitiesCount AS
Exists(
[Customer].[City].[City] // represents client sites
,[Customer].[State-Province].CurrentMember // represents client
).Count
MEMBER Measures.ClientCitiesSales AS
SUM(
[Customer].[State-Province].CurrentMember
,[Measures].[Internet Sales Amount]
)
MEMBER Measures.AvgAcrossClientCities AS
ClientCitiesSales/ClientCitiesCount
MEMBER Measures.IndustryCitiesCount AS
Exists(
[Customer].[City].[City] // represents industry sites
,Exists(
[Customer].[Country].[Country] // represents client's industry
,[Customer].[State-Province].CurrentMember // represents client
)
).Count
MEMBER Measures.IndustryCitiesSales AS
SUM(
Exists(
[Customer].[Country].[Country]
,[Customer].[State-Province].CurrentMember
)
,[Measures].[Internet Sales Amount]
)
MEMBER Measures.AvgAcrossIndustryCities AS
IndustryCitiesSales/IndustryCitiesCount
SELECT
{
[Measures].[Internet Sales Amount]
,ClientCitiesCount
,ClientCitiesSales
,AvgAcrossClientCities
,IndustryCitiesCount
,IndustryCitiesSales
,AvgAcrossIndustryCities
} ON 0,
{
[Customer].[City].[City] // represents client sites
} ON 1
FROM
[Adventure Works]
WHERE
[Customer].[State-Province].&[GA]&[US] // represents client
Don't forget to add in some edge-case handling (e.g. IIF the client has 0 "sites" in context) and consider using the "measuregroup" parameter in the EXISTS function.

MDX query to use a set but return a single row

I am new to MDX and have just started using Named sets to group several members of a dimension.
Whenever I use a SET in a query, the results returned are always detailed out for each individual member of the set. I am looking to get one one for the set.
For example: I have two Measures: Sales Dollars and Shipped Units. The then have a State dimension for each of the 50 states in the United States.
I want to see the Sales and Units measures for 3 specific states and then also for a group (Named Set) of 4 other states.
Example MDX:
With SET [My Favorite States] AS '{[States].[Illinois], [States].[Wisconsin]}'
select NON EMPTY {[Measures].[Sales], [Measures].[Shipped Units]} ON COLUMNS,
NON EMPTY {[States].[Alabama], [States].[New York], [My Favorite States]} ON ROWS
from [cubename]
This returns:
Measures
States Sales Shipped Units
Alabama $100 5
New York $500 20
Illinois $150 15
Wisconsin $900 25
What I want is for the Set to appear as a total on a single line. Similar to:
Measures
States Sales Shipped Units
Alabama $100 5
New York $500 20
My Favorite States $1,050 40
Is there an MDX function that will allow the set of specific members to be treated as a group?
You can use a calculated member to aggregate the separate states:
With Member [States].[My Favorite States] AS 'Aggregate({[States].[Illinois], [States].[Wisconsin]})'
select NON EMPTY {[Measures].[Sales], [Measures].[Shipped Units]} ON COLUMNS,
NON EMPTY {[States].[Alabama], [States].[New York], [States].[My Favorite States]} ON ROWS
from [cubename]