I Have a hieracy Defined a Level1 to Level5 and beneath that an Id.
I would like to create a calculated member that always makes the sum at the Level4.
currentMember.Parent works at Level5 but not at the Id Level.
What is the better way ?
Ok, Found it, With the Ancestors you can specify at what leve you want it.
WITH MEMBER Measures.Temp AS
SUM(Ancestors([Master Product].[Product Tree].CurrentMember,[Master Product].[Product Tree].[IBS Level 4]), [Measures].[Qty Master Product])
SELECT NON EMPTY { [Measures].[Qty Master Product], [Measures].[Qty Cross Product], Measures.Temp } ON COLUMNS,
NON EMPTY { [Master Product].[Product Tree].[IBS Level 5] } ON ROWS
FROM [ITS Cross Sales]
WHERE ( [Complex].[By Country].[Complex].&[3],
[Dates].[Calender].[Date].&[2013-03-17T00:00:00] )
Related
I have problem with my SSAS Cube.
I have to implement basic calculation to my Cube:
sum(Ammount) where BOOK = "Assets" and CD_PRODUCT_L4 <> "LoanLoss"
My dimmension is in image below:
Dimension attributes: BOOK, CD_PRODUCT_L4, CD_PRODUCT_L5, ..
Hierarchy PROD: CD_PRODUCT_L4 - CD_PRODUCT_L5
CREATE MEMBER CURRENTCUBE.[Measures].[Principal Loans]
AS (
except(
[PLV PRH HDIM CB].[BOOK].&[ASSETS_ON],
[PLV PRH HDIM CB].[COD PRODUCT L4].&[51L4]
),
[Measures].[EOM PRINCIPAL_a])
The biggest thing is that conditions are not from same hierarchy level so I can't use except and I know no other way to implement this particular condition set
Please HELP, Thank you
Product dimmension model
I manage to solve the issue by adding hierarchy to my dimension which allowed me to use except as I wanted before but I'am not satisfied with this solution because it looks more like workaround then solution
CREATE MEMBER CURRENTCUBE.[Measures].[Principal Loans] AS
sum((except([PLV PRH HDIM CB].[Hierarchy BOOK].[BOOK].&[ASSETS_ON].children,[PLV PRH HDIM CB].[Hierarchy BOOK].[COD PRODUCT L4].&[51L4]),[Measures].[EOM PRINCIPAL_a]))
This is probably the closest example that I can provide you to what you need.
This, code below, is just one of about 50 or so Measures we have defined, ranging from Counts, Averages, Sums, Percentages, etc. We take a single DW value and perform at least 2 seperation calculations, most have 4 or more different calculations, from that one field.
CREATE MEMBER CURRENTCUBE.[Measures].[Count Previous Difference]
AS Case
// Test for current coordinate being on (All) member.
When [Date].[YearMonth].CurrentMember.Level Is [Date].[YearMonth].[(All)]
Then "NA"
Else
( [Date].[YearMonth].CurrentMember, [Measures].[Gross Count] )
-
( ParallelPeriod (
[Date].[YearMonth].CurrentMember.Level,
1,
[Date].[YearMonth].CurrentMember
),
[Measures].[Gross Count]
)
End,
FORMAT_STRING = "#,##0.00;-#,##0.00",
NON_EMPTY_BEHAVIOR = { [Gross Count] },
VISIBLE = 0 , ASSOCIATED_MEASURE_GROUP = 'Some Summary';
Keep in mind we also use our DW & Cube with SharePoint and SSRS reports.
I have
Geography Dimension
-> Admin Hierarchy
-> Province level
-> District level
-> Facility level.
Now I want to find the geography data when province = 'BeiJing' and facility = 'test'. How should I do ?
I write MDX code like this:
SELECT
{} ON 0,
{[Geography.Admin].[BeiJing].[All Geography.Admin].[test]} ON 1
FROM [EIDCube]
but It doesn't work. How can I get all province/district/facility data as table when I set special province and facility ?
In AdvWrks the following throws an error
Query (4, 5) The Customer Geography hierarchy is used more than once
in the Crossjoin function.
This is thrown when I try to run the following:
SELECT
[Measures].[Internet Sales Amount] ON 0
,
[Customer].[Customer Geography].[Country]
*
[Customer].[Customer Geography].[State-Province] ON 1
FROM [Adventure Works];
The way around this is to use the attribute hierarchies which the levels of the [Customer Geography] user hierarchy is made up of, like this:
SELECT
[Measures].[Internet Sales Amount] ON 0
,
[Country].[Country]
*
[State-Province].[State-Province] ON 1
FROM [Adventure Works];
Now if I want Australia and Queensland I can cross-join a couple of single member sets:
SELECT
[Measures].[Internet Sales Amount] ON 0
,
{[Country].[Country].[Australia]}
*
{[State-Province].[State-Province].[Queensland]} ON 1
FROM [Adventure Works];
Results in this:
Edit
Applying the above to your structure you should be able to do something like this:
SELECT
{[Measures].[someMeasureInCube]} ON 0
,
{[Province].[Province].[BeiJing]}
* {[Facility].[Facility].[test]} ON 1
FROM [EIDCube];
Assuming your hierarchichal structure to be
Geography-->Geography.Admin-->Province-->District-->Facility
(dimension) (hierarchy) (level 1) (level 2) (level 3)
Here is the MDX to do it the long way(short way being directly feeding the values in query, which surprisingly didn't work)
select [Geography].[Geography.Admin].CHILDREN
having
[Geography].[Geography.Admin].currentmember.member_caption = "test" and
ancestors([Geography].[Geography.Admin].currentmember, 3).item(0).member_caption = "BeiJing"
on 1,
{} on 0
from EIDCube]
I think you can use this :
SELECT
{} ON 0,
([Geography].[Admin].[BeiJing],[Geography].[Admin].[Province].[District].[test]) ON 1
FROM [EIDCube]
Edit 1 : My previous answer was wrong.
So now I think the better solution is to create a new hierarchy [admin2] for the geography dimension composed of the level [Facility] only and to use this query.
SELECT
{} ON 0,
([Geography].[Admin].[BeiJing],[Geography].[Admin2].[Facility].[test]) ON 1
FROM [EIDCube]
We have a user hierarchy with 3 levels (Level1 being the upper level - Level3 the lower)
Using the FILTER function I state a string, this string could be within the member_name of any member from any (or several) of the levels. This returns a set.
I would then like all members from the hierarchy related to each item in the set; both upper and lower levels.
I've also tried (unsuccessfully) to include a column that is always Level2 in the results as a reference and also an ordering column.
WITH
MEMBER [Measures].[LevelName] AS
[DimensionX].[HierX].Level.Name
MEMBER [Measures].[LevelNumber] AS
[DimensionX].[HierX].Level.Ordinal
MEMBER [Measures].[MemName] AS //<<<<<not working as I want level 2 in the result set
[DimensionX].[HierX].currentmember.membervalue
SET [Set_Target] AS
{
FILTER(
[DimensionX].[HierX].AllMembers,
(
InStr(
1,
[DimensionX].[HierX].currentmember.name,
"jesus") <> 0
)
)
}
SELECT
// ORDER(
// Exists(
// [AttributeHierX].members,
// [Set_Target]
// ),
// [AttributeHierX].[AttributeHierX].MEMBERVALUE
// )
//*
ORDER(
DESCENDANTS(
[Set_Target],
[DimensionX].[HierX].[Level1],
SELF_BEFORE_AFTER
),
[Measures].[LevelNumber],
BASC
) as X
ON 1,
{
[Measures].[MemName],
[Measures].[LevelName],
[Measures].[LevelNumber]
} ON 0
FROM [CubeX]
I suppose a similar query on AdventureWorks delivers what you want:
WITH
MEMBER [Measures].[LevelName] AS
[Employee].[Employee Department].CurrentMember.Level.Name
MEMBER [Measures].[LevelNumber] AS
[Employee].[Employee Department].CurrentMember.Level.Ordinal
MEMBER [Measures].[MemName] AS
[Employee].[Employee Department].CurrentMember.Name
SET [Set_TargetEmp] AS
{
FILTER(
[Employee Department].AllMembers,
(
InStr(
1,
[Employee].[Employee Department].currentmember.name,
"WC4") <> 0
)
)
}
SELECT
{
[Measures].[MemName],
[Measures].[LevelName],
[Measures].[LevelNumber]
} ON 0,
Hierarchize(
Generate([Set_TargetEmp] as e,
Ascendants(e.Current)
+
Descendants(e.Current, e.Current.Level, SELF_AND_AFTER)
)
)
ON 1
FROM [Adventure Works]
I used Hierarchize to sort the result by hierarchy, as that seemed the most easy way for me to check the result. You may want to change that. As - in contrast to the Descendants method - Ascendants does not allow a set as the first argument, I used Generate to iterate along the set. Its default behavior (without a third argument of All), it eliminates duplicates, which I assumed is the behavior you need.
I'd like to be able to search the [Employee Department] hierarchy - within any of it's levels using a string: the following does this ok and finds all members related to the string "Control"
Now I have tried to add a cross join so that I can always see the department name for each of the rows and then ORDER by the department. If the commented section is uncommented I unfortunately get a full cartesian product - I only want the departments in the context of the members found by the filter - is this possible?
WITH
MEMBER [Measures].[LevelName] AS
[Employee].[Employee Department].Level.Name
MEMBER [Measures].[LevelNumber] AS
[Employee].[Employee Department].Level.Ordinal
SET [Set_TargetEmp] AS
{
FILTER(
[Employee Department].AllMembers,
(
InStr(
1,
[Employee].[Employee Department].currentmember.name,
"Control") <> 0
)
)
}
SELECT
// ORDER(
// [Department].members,
// [Department].[Department].MEMBERVALUE
// )
// *
ORDER(
DESCENDANTS(
[Set_TargetEmp],
[Employee].[Employee Department].[Department],
SELF_BEFORE_AFTER
),
[Measures].[LevelNumber],
BASC
) as X
ON 1,
{
[Measures].[LevelName],
[Measures].[LevelNumber]
} ON 0
FROM [Adventure Works]
Assuming you use Department the Department dimension, and the Employee Department is in a different dimension named Employee, you get a cross product. Analysis Services only applies "autoexists" within the same dimension. Across dimensions, you must apply this logic explicitly like this:
ORDER(
Exists([Employee].[Department Name].[Department Name].members,
[Set_TargetEmp]
),
[Department].[Department].MEMBERVALUE
)
for the commented block in your code should deliver what you want.
In case you have more than one measure group that relate to both the department and the employee dimensions, you should state the name of the measure group to use as the third argument of Exists. This is a string argument, hence this name should be included in quotes.
I'm using the following but i think there's probably a much simpler method of excluding the All members from the results?
WITH
SET [Non_All_Distributors] AS
{FILTER(
[Distributor Name].members,
(InStr(1, [Distributor Name].CurrentMember.NAME, "All") = 0)
)}
SET [Non_All_Countries] AS
{FILTER(
[Geography Country].members,
(InStr(1, [Geography Country].CurrentMember.NAME, "All") = 0)
)}
SELECT
NON EMPTY
[Dimension].[Hierarchy].DEFAULTMEMBER
ON COLUMNS,
NON EMPTY
[Non_All_Distributors]
*
[Non_All_Countries]
*
Tail([Date].[Date - Calendar Month].[Calendar Day].Members,60)
*
{
[Measures].[Revenue],
[Measures].[NumClients]
}
ON ROWS
FROM [OURCUBE]
Just use
SELECT
NON EMPTY
[Dimension].[Hierarchy].DEFAULTMEMBER
ON COLUMNS,
NON EMPTY
[dimension of Distributor Name].[Distributor Name].[Distributor Name].Members
*
[dimension of Geography Country].[Geography Country].[Geography Country].Members
*
Tail([Date].[Date - Calendar Month].[Calendar Day].Members,60)
*
{
[Measures].[Revenue],
[Measures].[NumClients]
}
ON ROWS
FROM [OURCUBE]
There is no need to define sets here. you can directly state the distributor and country members in the rows clause.
By repeating the attribute name, you restrict the attribute hierarchy - which you refer to by [dim].[attrib name] to the level below the All member, which happens to have the same name as the attribute again. An attribute hierarchy has two levels: level 0 contains the 'All' member and level 1 all the members of the attribute. (This is true only if you did not do special configurations like setting the attribute as non aggregateabable, but I assume the standard case, as you have All members in your hierarchies.
Apart from being more simple, this statement will run much faster, as Filter is a real performance killer in many cases.
I would use the Descendants function and the AFTER option as following; this way you get all the members of the hierarchy below the all member:
select
[Measures].[Amount] on 0,
Descendants([Customers].[Geography].[All], 1, AFTER ) on 1
from [Sales]
(edited: with a request working with MSAS Adv. Works : removed the distance param)
select
Measures].[Order Count] on 0,
Descendants( [Geography].[Geography].[All], , AFTER ) on 1
from [Adventure Works]