mdx a practical approuch

40
MDX A Practical View Glenn Schwartzberg

Upload: reiscc

Post on 24-Nov-2015

50 views

Category:

Documents


2 download

DESCRIPTION

advanced MDX tips

TRANSCRIPT

  • MDX A Practical View

    Glenn Schwartzberg

  • These slides the opinions of the presenter and do not constitute official positions of

    Oracle or any other organization. This material has not been peer reviewed

    and is presented here in spite of the better judgment of the presenter

    Disclaimer

  • Why this presentation?

    This presentation will attempt to demystify MDX because

    I sit through most presentations and at the end say Huh? (No offence Gary, most MDX presentations are over my head)

    Because of that

    I will attempt to show the basics with live practical examples.

    The examples are simple enough that even I can understand them and use them.

  • Agenda

    MDX Basics

    What the heck are we talking about

    Members

    CurrentMember

    Tuples

    Sets

    CrossJoins

    Emptyset

    (NonEmpty)

    Properties

  • Agenda -

    Continued

    Examples

    How to get Descendants

    Solve Order

    Rank

    ISValid

    (is it important?)

    Time Balance

    MTD/YTD functionality

    Lag/lead beginning period

    Rolling Average(single

    and multiple time dims)

  • MDX?

    A common Multidimensional Expression language that is common to OLAP products including:

    Microsoft Analysis Services

    Cognos

    Oracle BI

    Essbase

    Its a query language -

    Not a fully formatted

    reporting language

    Need to have some sort of front end program to format it.

  • Two uses with Essbase

    Query data from a database

    Block storage or Aggregate storage

    Select {[Sales],[COGS]} on Axis(0){[Market].Levels(0).members} on axis(1)From ASOSamp.BasicWhere [Jan]

    Create Member formulas

    Aggregate storage only[Sales]/[Cogs]

  • A Few Basics

    Members

    Just like in Essbase a single item in a hierarchy

    Represented as [MemberName] or

    [Parent].[MemberName] or

    [Dimension].[Parent].[MemberName] etc.

    Note braces instead of double quotes

    Last option necessary if you allow duplicate member names

  • Currentmember

    Very powerful

    One of the most important concepts in MDX

    Only use it if necessary

    [Jan] is more efficient than [Jan].Currentmember

    Determines location for a starting point of a calculation Product.currentmember

    Determines relative location for other functions Product.currentmember.parent

    Can be used to loop through members, but for a calculation a single member is considered

  • Tuples

    A combination of one or more dimensions to form a distinct intersection

    (like Cross dim ->

    in calc scripts)

    Only one member from a dimension allowed

    Every cell in the database is represented by a single tuple

    with all of the dimensions represented

    Enclosed in Parens

    Examples: ([Sales],[New York],[100-10], [Actual],[Jan]) ([Profit],[Markets],Products])

  • Sets

    Multiple members with the same dimensionality

    Can include 0, 1, or multiple Tuples

    Wrap in curly braces {} {[Period].levels(0).members} {([Scenario].[Actual],[Measures].[Sales]), ([Scenario].[Actual],[Measures].[Margin])}

    Why 0 tuples?

    Good for getting lists

  • Crossjoins

    Combines multiple sets together to create a superset

    of all the sets

    Enclosed in Parens(CrossJoin({[Jan],[Feb]}, {[Y-2009]}))

    = ([Jan], [Y-2009]) and ([Feb], [Y-2009])

    You can nest cross joins by using commas and parens

    Crossjoin(CrossJoin({[Jan],[Feb]}, {[Curr Year]}) ,{[Measures].[Units],[Measures].[Returns]})

  • Crossjoin

    Example

    SELECTCrossjoin(CrossJoin({[Jan],[Feb]},{[Curr Year]}) ,{[Measures].[Units], [Measures].[Returns]}) on Axis(0),

    {[Payment Type].levels(0).members} ON axis(1)from ASOSamp.Sample

  • Properties

    Used to get alternate member information

    Member_Alias

    (Default)

    Member_Name

    Gen_Number

    Level_Number

    Member_Unique_Name

    IS_Expense

    Comments (Hmmm -

    cant do this with other tools)

  • Properties

    Member names and Aliases

    Return is pretty ugly

    ({[Geography].Levels(2).members})PROPERTIES [MEMBER_Name] ON axis(1)

  • Removing Empty Rows

    We add the Non Empty directive to remove missing rowsNON EMPTY ({[Geography].Levels(2).members})PROPERTIES

    [MEMBER_Name] ON axis(1)

    Does not work well if you have multiple axis (I find you need to

    cross join them instead)

  • Another way

    Use a filter (which is probably better)

    Like Where

    syntax (just like SQL)

    Different from MDX Where clause

    Can be a member

    Or a comparison

    Can be crossjoins

    Filter({[Geography].Levels(2).members},[Measures]. [Units] > missing)

  • More on NonEmpty

    Version 11 offers new commands

    NonEmptyMember

    NonEmptyTuple

    NonEmptySubset

    Use for Formulas (same dimension(s) as in formula)

    Can significantly speed up calculations especially complex calculations

    Use NonEmptyTuple

    if it takes more than one dimension to determine missing

  • Getting Descendants

    In Calc formulas you could use @Descendants

    There is not a direct equivalent in MDX

    Instead we use Ancestors

    Sounds confusing

    How can we get descendants

    looking at ancestors?

    It is because

    The order of the members in the statement makes a difference

  • IsAncestor([stores].currentmember,[Great Buys]) (If the current member is an ancestor of Great Buys)DOES NOT EQUALIsAncestor([Great Buys],[stores].currentmember) (If Great Buys is an Ancestor of the current member)

    Lets take a look at a simple example:Case When IsAncestor([stores].currentmember,[Great Buys] ) Then 1 Else 2 EndCase When IsAncestor([Great Buys],[stores].currentmember ) Then

    1 Else 2 End

  • Solve Order

    Two Pass on steroids

    Allows you to set the order of calculation

    Best way to think of it is

    this happens before that

    Multiple types of Solve order

    Dimension

    Member

    WARNING

    -

    The order of precedence is different

    in different Essbase versions

    In 7X-

    the first equal wins in 9X and 11X the last

    wins

  • Rank

    No I dont mean the person sitting nearby that has not showered (or am I?)

    Use a With clause to create the member set to compare

    WITH MEMBER [Measures].[Sales_Rank] AS 'Rank(Product.CurrentMember, Product.levels(0).members)' SELECT {Sales, COGS, [Measures].[Sales_Rank]} ON COLUMNS, { Product.levels(0).members} ON ROWS FROM Sample.Basic;

  • ISValid

    Checks for valid intersections

    Using Prevmember, NextMember, Parent,Children

    etc

    Is this important?

    Only if you want correct answers. Example:

    Jan = 200, Feb = 300

    Current month

    prior month

    Easy for Feb 300

    200 = 100

    What about Jan

    Jan -

    ??? = 200??

    Time.currentmember.firstchild

    What if you are at the lowest level already?

  • ISValid

    ([Time].currentmember,[Units]) -

    ([time].currentmember.prevmember,[Units])

    CASE WHEN (ISValid([Time].currentmember.prevmember)) Then([Time].currentmember,[Units]) -([time].currentmember.prevmember,[Units]) ELSE Missing END

  • Time Balance

    In 11.X can do it natively, so why discuss it

    Gary will tell you in his ASO presentation about not making accounts the accounts dim.

    You will need another way to do it.

    Tag Time balance members with UDAs

    You can use similar logic for expense reporting or other special processing)

  • QTD/YTD functionality

    Not built into ASO cubes

    You could do this with alternate rollups

    Downside. Problems if

    You are using Time Balance (Periods needs to be stored)

    You want to use certain functions like ranges

    So how do you do it?

  • QTD/YTD functionality

    Create a View or Analytic dimension

    Must be a Dynamic dimension

    Store the first member

    Other members are calculated off of it

    Does it matter if the members are tagged with + or ~

    It depends. If dimension is label only then no, if not then yes

  • QTD/YTD Continued

    QTD=SUM(PeriodsToDate([Periods].Generation s(2), [Periods].CurrentMember), [View].[Periodic])

    YTD=SUM(PeriodsToDate([Periods].Generation s(1), [Periods].CurrentMember), [View].[Periodic])

    Note

    In Version 11, If you use timebalance use Aggregate instead of sum

  • Other COOL manipulations

    Lead,Lag,Firstchild,Lastchild, FirstSibling, LastSibling, ParallelPeriod.ClosingPeriod, etc.

    Good for ANY dimension

    Really good for time dimensions.

    Lead and Lag are like @Next and @prior or @PrevSibling or @NextSibling

    (New calcscript commands in 11X)

    No easy equivalent for Firstchild and Lastchild in Calcscripts.

    Lead and lag less efficient than FirstChild, ParallelPeriod, etc

  • Example

    SELECT{Sales} on axis(0) ,{[Jan],[Jan].lead(1),closingperiod([year].levels(0))} on Axis(1)FROM [Sample.basic]

  • Rolling Averages (One time dim)

    Easiest scenario

    Just have to lead or lag a range(dont forget ISVALID)

    with member [year].[rollavg] as 'AVG({[Jan]:[Jan].lead(11)}) 'SELECT{[sales]} on axis(0) ,{[year].[rollavg]} on Axis(1)FROM [Sample.basic]

  • Rolling Averages (two time dims)

    Documentation says it skips missing values, but in this case did not

    Use Avg and TupleRange to get members

    Use Case (or IIF) to make sure you are at proper level (if required) Necessary in my case as I hard coded end points.

    Hard coded end points is more efficient than using relative positioning (faster querying)

  • Case when (IsLeaf([time].currentmember) and not (IsEmpty([time].currentmember))) then

    AVG ({TUPLERANGE(

    ([years].currentmember.lag(1), [Time].currentmember.NextMember), ([Years].currentmember.lag(1), [Dec])), TUPLERANGE(

    ([Years].currentmember, [Jan]), ([Years].currentmember, [Time].currentmember))}

    , [Measures].[Units]) Else

    MissingEND

  • Head or Tail

    Used to get a subset of a range (another way to get range)

    For example

    I want the a 14 month rolling average with two time dimensions.

    Needs to be dynamic based on the selected time period

    Could span 3 years depending on what period I start with

    Will not work well if you have alternate rollups in periods.

  • Head Example

    SELECT {} ON AXIS(0),{HEAD(([FY2010], [Jan]) : ([Years].LastChild, ClosingPeriod([Periods].Levels(0))), 14)} ON AXIS(1)

    FROM [KScope.Test]

    To make dynamic change

    [FY2010], [Jan] to

    [Years].currentmember,

    [periods].currentmember

  • Flow Members

    New in 11X

    A Flow tag can be assigned to Accounts dimension members bearing formulas

    Assume you have Sales and Additions figures for all 12 months. You want to perform an aggregation to populate each months beginning inventory.

    Sales Additions InventoryJan 5 1 50Feb 6 3 46Mar 4 2 43Apr 7 0 41

  • Could do Inventory = SUM(MemberRange(Jan:Time.CurrentMember), (Additions - Sales)) + Beg_Inventory

    OR

    (Addition Sales), and tag the member as Flow

  • Restrictions on Flow

    Restrictions on Alternate Hierarchies

    If alternate hierarchies are used in the aggregate storage time dimension, the following restrictions apply when using Flow and TB tags on the Accounts dimension:

    The shared level among alternate time hierarchies must be level 0.

    The order of members at shared level among alternate time hierarchies must be the same in all alternate hierarchies.

  • [email protected]

    MDX A Practical ViewGlenn Schwartzberg These slides the opinions of the presenter and do not constitute official positions of Oracle or any other organization.This material has not been peer reviewed and is presented here in spite of the better judgment of the presenterWhy this presentation? AgendaAgenda - ContinuedMDX?Two uses with EssbaseA Few BasicsCurrentmemberTuplesSetsCrossjoinsCrossjoin ExamplePropertiesPropertiesRemoving Empty RowsAnother wayMore on NonEmptyGetting DescendantsSlide Number 20Solve OrderRankISValidISValidSlide Number 25Time BalanceQTD/YTD functionalityQTD/YTD functionality QTD/YTD ContinuedOther COOL manipulationsExample Rolling Averages (One time dim)Rolling Averages (two time dims)Slide Number 34Head or TailHead ExampleFlow MembersSlide Number 38Restrictions on FlowSlide Number 40