I am working with data in an OLAP-cube setup. I am wanting to display all Math Student Groups with the distinct student count for each group. Students get placed into a Math group based on how they scored on their math placement exam. They also get placed in every Math group lower than the one they placed into. (placed into Math 106, also a member of Math 105, 104, 103, 102, 101 and 100) Currently I am able to show only Math Groups on my rows and Distinct Students as a measure on the columns. The counts that display are only distinct per row and not for the entire report. So Math 100 group is displaying the count of all students in Math groups, not just Math 100.
WITH
/*- Qv6.0.3431.1887 -*/
SELECT
NON EMPTY
{
DISTINCT ( { [Measures].[Distinct Students] } )
}
PROPERTIES PARENT_UNIQUE_NAME, MEMBER_KEY, MEMBER_TYPE
ON COLUMNS,
NON EMPTY
{
{ [Student].[Student].[All Students] }
* { { { DISTINCT(
{ { FILTER(
{ { FILTER(
{ DESCENDANTS( [Student Group].[Student Group].[All Student Groups] , [Student Group].[Student Group].[Student Group]) } , InStr(1,IIF( ISERROR( [Student Group].[Student Group].CURRENTMEMBER.MEMBER_CAPTION ),"", [Student Group].[Student Group].CURRENTMEMBER.MEMBER_CAPTION ) , "Math") <> 0
) }
} , InStr(1,IIF( ISERROR( [Student Group].[Student Group].CURRENTMEMBER.MEMBER_CAPTION ),"", [Student Group].[Student Group].CURRENTMEMBER.MEMBER_CAPTION ) , "eligible") <> 0
) }
} ) }
} }
}
PROPERTIES PARENT_UNIQUE_NAME, MEMBER_KEY, MEMBER_TYPE
ON ROWS
FROM [Student Term]
WHERE ( [Terms].[Terms].[Term].&[138] )
CELL PROPERTIES FORMATTED_VALUE, VALUE, FONT_NAME
Here is a screenshot of the output:
Math Groups Student counts
I have tried searching all over here but was not successful in finding anything to help. I am by no means proficient in MDX, the reporting tool we use creates it based on what items we choose in the report builder (drag and drop mostly). The tool does allow you to create custom measures and elements using MDX. I really appreciate all assistance and please let me know if more information is needed.
Thanks!
====UPDATE 1-FEB-2017=======
thanks for your reply. I am finally getting to work on this again. I created custom measures in our front-end tool based on your code. I changed the [Measures].[StudentsCount] to [Measures].[Distinct Students] to match an available measure. If I select the 'StudentsCountDC' custom measure and run the report it returns nothing. If i select the 'IsStudentsTop' custom measure the counts it returns are extremely large like it isn't running for the selected term. Here is the new MDX that was generated after I ran the report with the newly created custom measure, 'StudentsCountDC'.
WITH
/*- Qv6.0.3431.1887 -*/
SELECT
NON EMPTY
{
DISTINCT ( { [Measures].[#~~2d0c2a98-fed9-4797-a573-170d3e450e4c~~#] } )
}
PROPERTIES PARENT_UNIQUE_NAME, MEMBER_KEY, MEMBER_TYPE
ON COLUMNS,
NON EMPTY
{
{ [Student].[Student].[All Students] }
* { [#~~9faf06d9-a022-493d-9dfd-dadd55793c37~~#] }
}
PROPERTIES PARENT_UNIQUE_NAME, MEMBER_KEY, MEMBER_TYPE
ON ROWS
FROM [Student Term]
WHERE ( [Terms].[Terms].[Term].&[136] )
CELL PROPERTIES FORMATTED_VALUE, VALUE, FONT_NAME
screenshots of new measures: IsStudentsTop & StudentsCountDC measures
Thanks again for your help!
It's a bit tricky, I personally haven't tested it yet. Hope, you'll get the point:
with
Member [Measures].[StudentsCountDC] as
SUM(
[Student].[Student].[Student].Members,
IIF(
not [Measures].[IsStudentsTop]
and
[Measures].[StudentsCount],
1,
NULL
)
)
Member [Measures].[IsStudentsTop] as
SUM(
{[Student Group].[Student Group].PrevMember:NULL},
[Measures].[StudentsCount]
)
IsStudentsTop checks whether StudentsCount exists in the upper groups (ordered by your attribute). StudentsCountDC checks if the current student has empty IsStudentsTop and StudentsCount is non empty, then returns 1 for each student, else returns Null.
Related
I work on a problem with an MDX Query.
The cube contains models and serials (units) and should show all units in warranty for each year.
This is the a cube with this Dimensions/Measures:
CubeOverview
Now I would select all Serials which are in warranty for a special year.
The problem is that the whole Table v Dim Unit Model 4IB Test contains more than 50 Mio rows which results alsways to an QueryTimeout or sometimes to an MemoryException.
At the moment I have a MDX query (see below) which works if I select special model. But I need the filter to all models.
WITH
MEMBER [Measures].[QtyTotal] AS
[Measures].[QtyInWarranty] + [Measures].[QtyInExtension]
SELECT
NON EMPTY
{
[Measures].[QtyStdOut] ,[Measures].[QtyInExtension] ,[Measures].[QtyStdIn]
,[Measures].[QtyInWarranty] ,[Measures].[QtyTotal] ,[Measures].[SumStartWarranty]
} ON COLUMNS
,NON EMPTY
{
crossjoin(
[v Dim Unit Model 4IB Test].[ModelUnitMapping].[Id Unit].Members
,[Dim Country].[Id Country].[Id Country].members
,[Dim Calendar].[Calendar].[Month Name4report].members
)
} ON ROWS
FROM
(
SELECT
{
[v Dim Unit Model 4IB Test].[model no short].[Model No Short].&[SampleModel]
} ON COLUMNS
FROM
(
SELECT
{
[Dim Calendar].[Calendar].[Year].&[2015]
} ON COLUMNS
FROM [InstalledBaseCS_Serial]
)
)
Does anybody knows a tip to update the query to get all units for one year (round about 4 Mio rows)?
If you're trying to return the results to a visible grid in MDXstudio or SSMS then it may be timing out because there is quite a bit to render.
If you use OPENQUERY or the CLR OLAP Extensions then try the following:
Do not return the results to the screen but INSERT results into a table.
Simplifiy your script by taking away the custom measure. This can easily be calculated later as it is trivial: I have a feeling it is slowing down ssas.
Script
SELECT
NON EMPTY
{
[Measures].[QtyStdOut]
,[Measures].[QtyInExtension]
,[Measures].[QtyStdIn]
,[Measures].[QtyInWarranty]
,[Measures].[SumStartWarranty]
} ON 0
,NON EMPTY
[v Dim Unit Model 4IB Test].[ModelUnitMapping].[Id Unit].Members
*[Dim Country].[Id Country].[Id Country].members
*[Dim Calendar].[Calendar].[Month Name4report].members
ON 1
FROM
(
SELECT
[v Dim Unit Model 4IB Test].[model no short].[Model No Short].&[SampleModel] ON 0
FROM
(
SELECT [Dim Calendar].[Calendar].[Year].&[2015] ON 0
FROM [InstalledBaseCS_Serial]
)
);
I have a hierarchy with 5 level,I use Descendants() to retrieve all lower level of a member.But i end up with a one column result where i like to have a result with one column for each level.So on each row i repeat the parent,grand parents etc of the current member.
WITH
MEMBER [Measures].[key] AS
[DimGLAcct].[MgtCOA].CurrentMember.UNIQUENAME
MEMBER [Measures].[level_] AS
[DimGLAcct].[MgtCOA].CurrentMember.level.ordinal
SELECT
{
[Measures].[key]
, [Measures].[level_]
, [Measures].[Actuals]
} ON COLUMNS,
{
Descendants(
[DimGLAcct].[MgtCOA].[Mparent5].&[MCOA].&[400000M - Total operating overhead expenses].&[440000M - Other expenses].&[441000M - Other expenses]
,
,SELF_AND_AFTER
)
} ON ROWS
FROM [Model];
I cannot quite suss out the names of your levels but it is ok to do the following in mdx:
WITH
MEMBER [Measures].[key] AS
[DimGLAcct].[MgtCOA].CurrentMember.UNIQUENAME
MEMBER [Measures].[level_] AS
[DimGLAcct].[MgtCOA].CurrentMember.level.ordinal
SELECT
{
[Measures].[key]
, [Measures].[level_]
, [Measures].[Actuals]
} ON COLUMNS,
[DimGLAcct].[LevelX]
*[DimGLAcct].[LevelY]
*[DimGLAcct].[LevelZ]
*[DimGLAcct].[LevelK]
ON ROWS
FROM [Model];
Each of the levels in your user hierarchy will have respective attribute hieraries - which are used in the above.
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 trying to write an MDX query with the equivalent SQL:
SELECT m.ID, m.CID, m.Orders
FROM dbo.Measures as m
WHERE SUBSTRING(m.CID, 1, 4) <> 'PID_'
Essentially, exclude all rows where CID begins with 'PID_'
This is what I have in MDX so far:
SELECT
{
[Measures].[ID] AS ID,
[Measures].[Orders] AS NumberOfOrders,
}
ON COLUMNS,
{
[Channel].[Channel Account ID].[Channel Account ID].Members
* [Channel].[Channel].[Channel].Members // exclude accounts starting with 'PID_'
}
I've tried EXCEPT and - and WHERE clauses, but none seem to work.
Any help is appreciated!
I found the answer with the links xQbert provided.
This was the answer:
ON COLUMNS,
{
FILTER([Channel].[Channel Account ID].[Channel Account ID].Members,
LEFT([Channel].[Channel Account].Properties("Channel Account ID"), 4)
<> "PID_")
* [Channel].[Channel].[Channel].Members
}
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