mdx - what bi developers need to know
DESCRIPTION
This is an introductory look at MDX presented by Nathan Peterson of Solid Quality Mentors Every developer should be able to write the MDX needed to create Key Performance Indicators (KPIs) to meet business requirements. This short session will give you a solid introduction to the language, so that you can start using its power to give your business the information it needs. You will learn how to: * Think multi-dimensionally to better understand how cube data works * Use MDX, the query language for Analysis Services * Create Named Sets and Calculated Members with MDX to meet business needsTRANSCRIPT
What All Microsoft BI Developers What All Microsoft BI Developers Need to Know About MDXNeed to Know About MDX
Speaker: Nathan Peterson
Solid Quality Mentors
Silicon Valley SQL Server User Group
January 19, 2009
Mark Ginnebaugh, User Group Leader, [email protected]
Nathan PetersonNathan Peterson
� Solid Quality Mentors
�Currently working on an Analysis Services project for the US Army
� Lead developer of a local cube generating utility called CubeSlice
What do all developers need to know about What do all developers need to know about MDX? MDX?
� You should be able to:
� Create and debug Calculated Members.
� Create and debug Named Sets.
What you need to know to accomplish this:� What you need to know to accomplish this:
� Understand MDX Concepts.
� Learn MDX Syntax.
� Learn some MDX functions.
� Learn some practical applications of MDX.
What Is MDX?What Is MDX?
� Multi-Dimensional eXpressions
� SQL is used for relational queries, while MDX is used for multidimensional queries.
� Calculated members allow you to incorporate � Calculated members allow you to incorporate multidimensional logic into your cube.
� Named sets allow you to pre-define dynamic groups of members to be displayed on columns or rows.
Sample calculated memberSample calculated member
with member measures.[Last Year Sales Amount]as(measures.[Sales Amount], measures.[Sales Amount], ParallelPeriod
([Date].[Calendar].[Calendar Year],1,[Date].[Calendar].CurrentMember)
)
Sample named setSample named set
with set [Top 5 Products]astopcounttopcount
([Product].[Product].Members,5,Measures.[Internet Sales Amount])
Comparing MDX to SQLComparing MDX to SQL
� From
� SQL selects from a table.
�MDX selects from a cube.
� Dimensionality � Dimensionality
� SQL returns one or more columns and 0 or more rows.
�MDX can return data for 0, 1, 2, 3 or more axes.
� Where
� SQL has a filter.
�MDX has a slicer.
MDX query with two axes and two slicersMDX query with two axes and two slicers
select Measures.AllMembers on columns,[Date].[Calendar].&[2003].Children on rowsfrom [Adventure Works]from [Adventure Works]where ([Customer].[Customer Geography].[France],[Product].[Product Categories].[Bikes])
Dimensions and MeasuresDimensions and Measures
Same query, using axis numbers instead of axis Same query, using axis numbers instead of axis namesnames
select Measures.AllMembers on 0,[Date].[Calendar].&[2003].Children on 1from [Adventure Works]from [Adventure Works]where ([Customer].[Customer Geography].[France],[Product].[Product Categories].[Bikes])
Using MDX requires multidimensional thinkingUsing MDX requires multidimensional thinking
� In a cube
� Dimensions have hierarchies
� Hierarchies have levels
� Levels have members� Levels have members
� In a cellset
� Each axis contains a set
� Each set consists of a group of members or a group of tuples
� Tuples have members from different hierarchies
Multidimensional thinking Multidimensional thinking –– Where are you?Where are you?
� Every member is in a level.
� Every level is in a hierarchy.
� Every hierarchy is a part of a dimension.
� For every cell of the cellset, there’s (almost) always a Current Member for each hierarchy.
� The Current Member may be set from the column, the row, the slicer, or the default member.
Create a set by listing membersCreate a set by listing members
� The simplest set is a list of members.
� The boundaries of the set are indicated with curly braces {}.
selectselect{[Product].[Category].[All Products],[Product].[Category].[Accessories],[Product].[Category].[Bikes],[Product].[Category].[Clothing],[Product].[Category].[Components]} on 0from [Adventure Works]
Create a set with a functionCreate a set with a function
� There are many MDX functions that create sets.
� This query uses the .Members function to return all the members from a hierarchy – and gives the same result as the previous query.result as the previous query.
� You don’t have to use {} when you create a set with a function.
select [Product].[Category].Members on 0from [Adventure Works]
TuplesTuples
� Each cell in a cellset shows data for one particular member from each hierarchy.
� A tuple is a way of specifying which member should be used from each of the hierarchies.be used from each of the hierarchies.
� Tuples are written like points in a geometric grid:
� (6,3) identifies point 6 on the x-axis and point 3 on the y-axis.
� ([2009],[US],[Bikes],[Internet Sales Amount]) identifies Internet Sales for Bikes in the US in 2009.
2 Dimensional 2 Dimensional TupleTuple
6
5
4
3
2 Dimensional Tuple
1 2 3 4 5 6 7 8
3
2
1
(6, 2)
Create a set by listing tuplesCreate a set by listing tuples
select{([Date].[Calendar Year].&[2002],[Product].[Category].[Accessories]),(
[Date].[Calendar Year].&[2002],[Date].[Calendar Year].&[2002],[Product].[Category].[Bikes]),(
[Date].[Calendar Year].&[2003],[Product].[Category].[Accessories]),(
[Date].[Calendar Year].&[2003],[Product].[Category].[Bikes])
}
on 0from [Adventure Works]
Listing Listing TuplesTuples
([2006], [Mountain Bikes])
2 Dimensional Tuple
[Accessories]
[Clothing]
[Touring Bikes]
[Road Bikes]
1 2 3 4 5 6 7 8
([2006], [Mountain Bikes])
2 2 2 2 2 2 2 20 0 0 0 0 0 0 00 0 0 0 0 0 0 0
[Road Bikes]
[Mountain Bikes]
[All Products]
Create a set of tuples by multiplying two sets of Create a set of tuples by multiplying two sets of membersmembers
select {
[Date].[Calendar Year].&[2002],[Date].[Calendar Year].&[2003]
}}*{
[Product].[Category].[Accessories],[Product].[Category].[Bikes]
}on 0from [Adventure Works]
3 Dimensional 3 Dimensional TupleTuple
[Accessories]
[Clothing]
[Touring Bikes]
[Road Bikes]([2006], [Mountain Bikes], [Red])
3 Dimensional Tuple Difficult to Show in 3 Axes –Where to place the point?
1 2 3 4 5 6 7 8
[Road Bikes]
[Mountain Bikes]
[All Products]
([2006], [Mountain Bikes], [Red])
2 2 2 2 2 2 2 20 0 0 0 0 0 0 00 0 0 0 0 0 0 0
[Red][Blue]
[Pink]
3 Dimensional 3 Dimensional TupleTupleCombining 2 Hierarchies on 1 AxisCombining 2 Hierarchies on 1 Axis
([Blue], [Road Bikes])
([Red], [Road Bikes])
([Blue], [Mountain Bikes])
([Red], [Mountain Bikes])
3 Dimensional Tuple
1 2 3 4 5 6 7 8
([Red], [Mountain Bikes])
([Blue], [All Products])
([Red], [All Products])([2006], [Mountain Bikes], [Red])
2 2 2 2 2 2 2 20 0 0 0 0 0 0 00 0 0 0 0 0 0 0
The Where clauseThe Where clause
� The Where clause is an optional part of an MDX query.
� The Where clause is a slicer, not a filter.
� You can’t use the Where clause for limiting the value to � You can’t use the Where clause for limiting the value to a threshold (Sales over $10,000).
� Use the Filter function for filtering.
� The Where clause often looks like a tuple and actually is a tuple – but it doesn’t have to be.
Where clause using a tuple Where clause using a tuple –– one member from one member from each referenced hierarchyeach referenced hierarchy
select Measures.[Internet Sales Amount] on 0from [Adventure Works]from [Adventure Works]where ([Customer].[Customer Geography].[France],[Product].[Product Categories].[Bikes])
Where clause with slicing on multiple members Where clause with slicing on multiple members from one hierarchyfrom one hierarchy
select Measures.[Internet Sales Amount] on 0from [Adventure Works]where where ([Customer].[Customer Geography].[France],
{[Product].[Product Categories].[Bikes],[Product].[Product Categories].[Clothing]}
)
The With clauseThe With clause
� The With clause is used for creating both calculated members and named sets.
� These calculated members and named sets are only valid for the life of the query.valid for the life of the query.
� You can also create calculated members and named sets that are persistent:
� Lasting for the life of a session.
� Created permanently in the cube.
Creating calculated member in the With clauseCreating calculated member in the With clause
with member Measures.[Average Internet Sales]as[Measures].[Internet Sales Amount][Measures].[Internet Sales Amount]/[Measures].[Internet Order Count],format_string = "currency"select {Measures.[Average Internet Sales]} on 0from [Adventure Works]
Members, Sets, Members, Sets, TuplesTuples
Set of
(Partial)
([Blue], [Road Bikes])
([Red], [Road Bikes])
([Blue], [Mountain Bikes])
([Red], [Mountain Bikes])
Members, Sets, Tuples
Member
Set of Members
(Partial)
Tuples
1 2 3 4 5 6 7 8
([Red], [Mountain Bikes])
([Blue], [All Products])
([Red], [All Products])([2006], [Mountain Bikes], [Red])
(Partial) Tuple
2 2 2 2 2 2 2 20 0 0 0 0 0 0 00 0 0 0 0 0 0 0
Creating named set in the With clauseCreating named set in the With clause
with set [Products - High Selling on Internet]asfilter
(([Product].[Product].[Product].Members,[Measures].[Internet Sales Amount]
> 50000)
select {Measures.[Internet Sales Amount]} on 0,[Products - High Selling on Internet] on 1from [Adventure Works]
Full Full TupleTuple
([Blue], [Road Bikes])
([Red], [Road Bikes])
([Blue], [Mountain Bikes])
([2006], [Mountain Bikes], [Red], [All
Promotions], [All Gender],
[Measures].[Reseller Sales Amount],
etc…)
1 2 3 4 5 6 7 8
([Red], [Mountain Bikes])
([Blue], [All Products])
([Red], [All Products])
etc…)
2 2 2 2 2 2 2 20 0 0 0 0 0 0 00 0 0 0 0 0 0 0
MDX PunctuationMDX Punctuation
� Use {} for sets.
� Use () for tuples.
� Use [] for names of cubes, dimensions, hierarchies, � Use [] for names of cubes, dimensions, hierarchies, levels, and members.
� Use commas all over the place (except not between multiple calculated members or named sets defined in the same query).
Where to write your MDXWhere to write your MDX
� In a client application like PerformancePoint, which allows you to write code for calculated measures and sets.
In a query editor like the SQL Server Management � In a query editor like the SQL Server Management Studio.
� In the MDX Script of a cube.
TIP: It’s often easier to write the code in a query editor first and then put it into the MDX Script.
Writing MDX for a KPIWriting MDX for a KPI
� You can write MDX to create the values for a KPI, whether you’re working with Analysis Services KPIs or PerformancePoint Services KPIs.
For both tools, it’s easier to create calculated � For both tools, it’s easier to create calculated members in the MDX script for the values first.
� TIP: When building KPIs in the BIDS, use a template for assigning the Status and the Trend.
Functions Functions –– Navigating within a levelNavigating within a level
� PrevMember
� NextMember
� Lag()� Lag()
� Lead()
Examples of navigating in a levelExamples of navigating in a level
� Navigation functions are often used with Dates.
� Note: PrevMember, Lag(1), and Lead(-1) all return the same member.
[1997].PrevMember[1997].PrevMember[1996]
[March 2010].NextMember [April 2010][10 April 2009].Lag(2) [8 April 2009][December 2009].Lead(12) [December 2010]
Functions Functions –– All in the FamilyAll in the Family
� Parent
� Children, FirstChild, LastChild
� DescendantsDescendants
� Ancestor, Ascendants
� Siblings, FirstSibling, LastSibling
� Cousin
Examples of family functionsExamples of family functions
� Some of the family functions return individual members, while other return sets.
� If a function returns an individual member, you can use another function with it.
[Mar 1997].Parent [1997][Q1 2009].Children [Jan 09]:[Mar 09][2009].FirstChild [Q1 2009]Descendants([2009], 2) [Jan 09]:[Dec 09]Descendants([2009],[Date])[1Jan09]:[31Dec09]Ancestor([Mar 2008], 3) [2008]FirstSibling([Mar 2007]) [Jan 2007]
Functions Functions –– Multiplying, adding, subtracting, Multiplying, adding, subtracting, intersecting setsintersecting sets
� Set multiplication, addition, and subtractions can be indicated with mathematical symbols or with functions.
Multiplication * Crossjoin
Addition + Union
Subtraction - Except
Intersection Intersect
Example of set multiplicationExample of set multiplication
� These two sets are equivalent.
[Date].[Fiscal].[Month].members* [Product].[Product].members[Product].[Product].members
Crossjoin([Date].[Fiscal].[Month].members,[Product].[Product].members)
Practical Applications of MDXPractical Applications of MDX
� Comparing with a previous time period.
� Comparing with the same time period in the previous year.
� Year-To-Date.
� Rolling Average.
� Percent contribution.
Comparing with a previous time periodComparing with a previous time period
with member Measures.[Last Month Sales]as(Measures.[Internet Sales Amount],[Date].[Calendar].PrevMember[Date].[Calendar].PrevMember)select{Measures.[Internet Sales Amount],Measures.[Last Month Sales]} on 0,[Date].[Calendar].[Month].members on 1from [Adventure Works]
Comparing with the same period in the previous Comparing with the same period in the previous yearyear
with member measures.[Last Year Sales Amount]as(measures.[Sales Amount], measures.[Sales Amount], ParallelPeriod
([Date].[Calendar].[Calendar Year],1,[Date].[Calendar].CurrentMember)
)
YearYear--ToTo--Date Date
with member measures.[YTD Sales]assum(ytd([Date].[Calendar].CurrentMember),ytd([Date].[Calendar].CurrentMember),Measures.[Internet Sales Amount])
select{Measures.[Internet Sales Amount],Measures.[YTD Sales]} on 0,[Date].[Calendar].[Month].members on 1from [Adventure Works]
Rolling AverageRolling Average
With member measures.[Previous 6 Month Rolling AVG]assum([Date].[Calendar].lag(6):[Date].[Calendar].lag(6):[Date].[Calendar].lag(1),
Measures.[Internet Sales Amount]) / 6
select{Measures.[Internet Sales Amount],Measures.[Previous 6 Month Rolling AVG]} on 0,[Date].[Calendar].[Month].members on 1from [Adventure Works]
Percent ContributionPercent Contribution
With member Measures.[Percent of Parent Sales]asMeasures.[Internet Sales Amount]/(Measures.[Internet Sales Amount],Measures.[Internet Sales Amount],[Product].[Product Categories].Parent)
select{Measures.[Internet Sales Amount],Measures.[Percent of Parent Sales]} on 0,[Product].[Product Categories]. members on 1from [Adventure Works]
Additional topics Additional topics –– if there’s timeif there’s time
� Dealing with exceptions
� String manipulation
� GenerateGenerate
� Recursion
Dealing with exceptionsDealing with exceptions
� A calculation needs to be valid everywherewith member [Measures].[% Change # of Customers]ascasewhen [Date].[Fiscal].CurrentMember.Level.Ordinal = 0 then "NA” when [Date].[Fiscal].CurrentMember.Level.Ordinal = 5 then Null when [Date].[Fiscal].CurrentMember.Level.Ordinal = 5 then Null when isempty
( ([Date].[Fiscal].CurrentMember.PrevMember, [Measures].[Customer Count])) then null
else( ([Date].[Fiscal].CurrentMember, [Measures].[Customer Count])-([Date].[Fiscal].PrevMember, [Measures].[Customer Count])) /([Date].[Fiscal].PrevMember,[Measures].[Customer Count])end
Functions Functions -- String manipulationString manipulation
� Turning the current date into a member reference
Strtomember((
"[Date].[Fiscal].[Date].&["+ cstr(year(now()) - 6)+ right("0" + cstr(month(now())), 2)+ right("0" + cstr(day(now())), 2)+ "]"
)
The Generate functionThe Generate function
� What are the five top products most purchased by people living in my top five cities?
generate(topcounttopcount([Customer].[Customer Geography].[City].members,5,[Measures].[Internet Sales Amount] ),
crossjoin([Customer].[Customer Geography].CurrentMember,topcount([Product].[Product].[Product].members,5,[Measures].[Internet Sales Amount]
) ) )
RecursionRecursion
� Finding the most recent purchase
with member measures.[Most Recent Purchase]member measures.[Most Recent Purchase]asiif
([Measures].[Internet Sales Amount] > 0,[Measures].[Internet Sales Amount],[Date].[Calendar].PrevMember)
Thank youThank you
� http://www.databasejournal.com/article.php/1459531/
� http://msdn.microsoft.com/en-us/library/ms145970.aspx
� http://www.sqlserveranalysisservices.com
� http://www.ssas-info.com/analysis-services-faq/27-mdx
� http://www.mosha.com/msolap/mdx.htm
� http://cwebbbi.spaces.live.com
To learn more or inquire about speaking opportunities, please contact:
Mark Ginnebaugh, User Group Leader