dcsimg

Logical Functions: IsAncestor(): Conditional Logic within Calculations - Page 2

February 5, 2007

Practice

Preparation: Access SQL Server Management Studio

To reinforce our understanding of the basics we have covered, we will use the IsAncestor() function within a couple of queries that illustrate its operation, focusing, within this article, upon scenarios where we use the function to support conditional logic within a calculation. (We examine its use in combination with the MDX Filter() function in another article of this series). We will undertake our practice exercises within scenarios that place IsAncestor() within the context of meeting basic requirements similar to those we might encounter in our respective daily environments. The intent is to demonstrate the use of the function in a straightforward, memorable manner.

We will turn to the SQL Server Management Studio as a platform from which to construct and execute the MDX we examine, and to view the results datasets we obtain. If you do not know how to access the SQL Server Management Studio in preparation for using it to query an Analysis Services cube (we will be using the sample Adventure Works cube in the Adventure Works DW Analysis Services database), please perform the steps of the following procedure, located in the References section of my articles index:

Prepare MSSQL Server Management Studio to Query Analysis Services

This procedure will take us through opening a new Query pane, upon which we will create our first query within the section that follows.

Procedure: Satisfy Business Requirements with MDX

Let’s assume, for purposes of our practice example, that we have received a request for assistance from representatives of our client, the Adventure Works organization. Analysts within the Controllers’ Group, with whom we have worked in the past to deliver solutions to meet various reporting and analysis needs, inform us that they have received a request to generate some simple values for a specific analysis task that has been discussed at a recent meeting with the Controllers.

The analysts tell us that the values under immediate consideration involve Internet Order Counts, but, as is typically the case in our collaborative sessions, they want to develop an approach that will work equally well with other measures that have similar analysis potential. (They often derive parameterized queries in Reporting Services from the basic MDX syntax we assemble together, and can thus create self-serve reports that allow information consumers to dictate what measure they wish to analyze, and myriad other options, at run time). The desired end is to simply return the Internet Order Count recorded for each day, month, quarter, and semester for a given operating calendar year.

While this basic need might be easily met a number of ways with an MDX query, the analysts throw a further twist into the requirement: In addition to being likely to parameterize the calendar year at runtime, they also want to be able to support parameterization of the level within the Date dimension (Calendar hierarchy) when executing the report (that is, to be able to change it from calendar year to a lower level, such as a quarter of a month, for example – and thus to “narrow” the member selection that appears within a given iteration of the report results, producing something akin to a selective “drilldown” effect.) Once again, the richness of MDX affords us a number of avenues to this objective. While parameterization is itself not a consideration in our current level of query design, we want to make it easy to accomplish within Reporting Services (the same concept would, of course, apply with other OLAP reporting tools that afford developer access to the MDX syntax that underlies them).

After we initially explain the use of the IsAncestor() function as one candidate for meeting the requirement, our client colleagues state that they are interested in understanding how they might apply conditional logic via this function, within the context of a practical scenario such as the immediate requirement. A method of testing whether or not a specified member is an ancestor to another specified member, or group of members, is something that they hope to be able to extrapolate to uses with other dimensions, as well. (Time / date dimensions are always good “starters” for introducing new functions: the relationships between the various levels are familiar to everyone, whereas the structures of other dimensions might not lend themselves to population accuracy and completeness “reasonability” testing undertaken by those not entirely knowledgeable of the corporate structure, geography, and so forth.)

We offer to illustrate the use of IsAncestor() to meet the immediate need, proposing to present a couple of examples, to solidify the analysts’ new understanding, as well as to assist in rounding their overall MDX “vocabularies.” We then set about the assembly of our examples to illustrate uses of IsAncestor().

Procedure: Use the IsAncestor() Function to Perform Conditional Logic within a Calculation

Per the request of our client colleagues, we will first construct a simple query to provide an illustration of the use of the IsAncestor() function within a common context, the definition of a calculation based upon conditional logic. Our initial example will serve as an introduction to a means of distinguishing the presence of a ancestor / descendant relationship between members of the Date dimension. (We will work with Calendar Year 2003, as the primary member, within our initial example), as requested by the analysts, as a basis for meeting the business requirement to present the simple Internet Order Counts at multiple levels.

1.  Type (or cut and paste) the following query into the Query pane:


-- MDX052-001 ISANCESTOR()Function: Conditional Logic in 
--   the Definition of a Calculation

WITH 
MEMBER
   [Measures].[InternetSelectCount]
AS
   'IIF(
   
      ISANCESTOR([Date].[Calendar].[Calendar Year].[CY 2003], 
         [Date].[Calendar].CURRENTMEMBER),
      [Measures].[Internet Order Count],
   
   NULL)'
   
SELECT
   {[Measures].[InternetSelectCount]}ON AXIS(0),
   NON EMPTY{[Date].[Calendar].MEMBERS} ON AXIS(1)
FROM 
 [Adventure Works]

The Query pane appears, with our input, as depicted in Illustration 2.


Illustration 2: Our Initial Query in the Query Pane ...

The above query returns the Internet Order Count for each member of the Date dimension (Calendar hierarchy) in the cube – whose ancestor is Calendar Year 2003 – regardless of the level the member inhabits; we use Non Empty to physically screen the results to show our “focus” Calendar Year, 2003, and the descendants of this specified, year-level primary member expression. Had we not inserted the Non Empty keyword, we would get all members of the Date dimension, Calendar hierarchy, with those non-descendant members simply indicating (null) as a measure value.

Recall that we have said that we might accomplish our ends through alternative methods. The approach we are taking here allows us to parameterize the primary member expression to accomplish the extended ends of our client colleagues. In doing so, we could set up a hierarchical picklist within Reporting Services, whereby information consumers might select a given date, month, quarter, and so forth, to drive the level below which values are returned. The obvious advantage is that consumers can dictate both the level of the date hierarchy and the specific “focus” member of the hierarchy itself, within the level (in our example, the year for which they wish to display the value for the corresponding descendants). In some circumstances such “double leverage” provided by a single parameter might be seen as a highly desirable efficiency – certainly within the realm of simulated dynamic drilldown effects and so forth.

In the Tentative Reseller Share calculation, we put the IsAncestor() function to work in applying conditional logic to generate the Internet Order Count value: if Calendar Year 2003 (the primary member expression of our function) is the ancestor of the secondary member expression (the Current Member of the Date dimension / Calendar hierarchy), then the corresponding Internet Order Count value is presented. Alternatively, we have directed (via the conditional logic of the IIF() function), that if the primary member expression (Calendar Year 2003) is not the ancestor of the secondary member expression (that is, the member is not a dimensional descendant of Calendar Year 2003), than the Internet Order Count value is returned as null. (Moreover, as we have noted, while we might have displayed all values, including nulls, we eliminated nulls in our present exercise by preceding the rows specification with the NON EMPTY keyword.)

NOTE: For more detail surrounding the IIF() function, see String / Numeric Functions: Introducing the IIF() Function and String / Numeric Functions: More on the IIF() Function. For more about the .CurrentMember function, see MDX Member Functions: "Relative" Member Functions. All articles are members of the Database Journal MDX Essentials series.

For more information about, and hands-on practice with, the sort of parameterization of MDX queries to which I refer within this article, see various member articles of my MSSQL Server Reporting Services series.

We have specified that the Calendar Date members are to populate the rows axis. This provides, to some extent, a quick means of “reasonability” testing out the logic within the calculation that we have defined, as we shall see.

2.  Execute the query by clicking the Execute button in the toolbar, as shown in Illustration 3.


Illustration 3: Click Execute to Run the Query...

The Results pane is populated by Analysis Services, and the dataset, partially depicted in Illustration 4, appears.


Illustration 4: Results Dataset (Partial View) – IsAncestor() Function within a Calculation

In the partial view of the returned dataset, we see that the calculation accomplishes the intended purpose - generating the Internet Order Count for the individual Date (Calendar hierarchy) descendants of Calendar Year 2003, which share the same ancestor (Calendar Year 2003). Again, the conditional test of “ancestry” is applied via a calculated member within which we have leveraged the IsAncestor() function.

3.  Select File -> Save MDXQuery1.mdx As ..., name the file MDX052-001, and place it in a meaningful location.

Our client colleagues express satisfaction with the contextual backdrop we have established for introducing the IsAncestor() function. We will use a similar query within another such example next, to confirm understanding of the concepts. This query will provide an illustration of the use of the IsAncestor() function within the context we have already seen, the definition of a calculated member based upon a comparison. As before, we will base our example upon a local, albeit slightly more sophisticated, scenario described by the client representatives.

The developers / authors within the group cite the following example as useful. They would like to create a query that returns a tentative calculation for Net Resale Revenues, based upon a recent proposal for determining Reseller share of a Product sale for operating Calendar Year 2003. The team provides the following, “example-only” details, as final details are currently being negotiated: for purposes of the example, we would like to calculate Reseller share for Bike (our primary product) sales as 7.5 percent of Reseller Sales Amount; Reseller share for all other Product sales would be calculated at 5.75 percent.

To refresh our memory of the dimensional structure under consideration, we examine the expanded Product Categories hierarchy of the Product dimension, within the Adventure Works cube. A partial view of this structure appears as shown in Illustration 5.


Illustration 5: Partial View of the Product Categories Hierarchy – Product Dimension








The Network for Technology Professionals

Search:

About Internet.com

Legal Notices, Licensing, Permissions, Privacy Policy.
Advertise | Newsletters | E-mail Offers