# MDX Set Functions: The DRILLUPMEMBER() Function - Page 2

January 3, 2006

### The DrillUpMember() Function

#### Introduction

According to the Books Online, the DrillUpMember() function "returns a set of members based on the members included in the set specified in Set1 that are descendants of members in Set2." The set of child members returned by DrillUpMember() is ordered according to the arrangement within the primary set. DrillUpMember() assembles the set by including only those members specified in the primary set that are immediate descendants of members specified in the secondary set.

DrillUpMember() has many applications, and pairing it with other MDX functions can help us to leverage its power even further. I frequently use it in combination with various functions, including the Descendants() function and others. We will examine in detail the syntax for the DrillUpMember() function after our customary overview in the Discussion section that follows. Following that, we will conduct practice examples within a couple of scenarios, constructed to support hypothetical business needs that illustrate uses for the function. This will afford us an opportunity to explore some of the delivery options that DrillUpMember() can offer knowledgeable developers and / or report authors. Hands-on practice with DrillUpMember(), wherein we will create a query that leverages the function, will help us to activate what we learn in the Discussion and Syntax sections.

#### Discussion

To restate our initial explanation of its operation, the DrillUpMember() function builds a set of the members based upon a specified primary set which are descendants of members of a specified secondary set. The primary set can have any dimensionality, but the secondary set must be of a single dimension, as we shall see.

If the secondary set does not contain an immediate ancestor for a given member within the primary set, then that primary set member is not "drilled up"; the member is simply returned as it appears within the primary set. In plain terms, if an immediate ancestor of a given primary set member exists in the specified secondary set, then that ancestor is returned ("drill up" to the ancestor occurs within the set returned by the function). Alternatively, any member specified in the primary set without an immediate ancestor in the secondary set is simply returned as its "not drilled up" self. The descendants in the primary set with immediate ancestors in the secondary set are themselves returned, as well, with the ultimate result being the member(s) and the "rolled up" ancestor(s) appearing in the same returned set.

The primary set can consist of tuples instead of members. In cases like this, a set of tuples is returned instead of a set of members. As we noted earlier, we can specify mixed dimensionality in the primary set, but the secondary set can be specified only as a single dimension.

When we couple it with other functions, we can leverage DrillUpMember() to deliver a wide range of analysis and reporting utility. As is often the case with the Microsoft integrated Business Intelligence solution, consisting of MSSQL Server, Analysis Services and Reporting Services, this function, residing within the Analysis Services layer, can be extended to support capabilities and attributes in the Reporting Services layer. Knowing "where to put the intelligence" among the various layers is critical to optimization, in many cases. For more of my observations on this subject, see Multi-Layered Business Intelligence Solutions ... Require Multi-Layered Architects.

Let's look at some syntax illustrations to further clarify the operation of DrillUpMember().

#### Syntax

Syntactically, anytime we employ the DrillUpMember() function to drill up by a member, the effect of the function, as we have seen, is to drill up those members of the specified primary set for which immediate ancestors appear within the specified secondary set. We specify the two sets within the parentheses to the right of the DrillUpMember keyword. The general syntax is shown in the following string:

`DrillUpMember(Set1,Set2)`

(Set1 in the string represents the "Primary Set" to which I refer throughout our discussion. Set2 represents the "Secondary Set.")

Let's take a look at an example. The following snippet employs the DrillUpMember() function:

```
DRILLUPMEMBER( {[Geography].[Geography].[State-Province].[California],
[Geography].[Geography].[City].[Canoga Park],
[Geography].[Geography].[City].[Carson],

[Geography].[Geography].[City].[Citrus Heights],
[Geography].[Geography].[City].[Fullerton],

[Geography].[Geography].[State-Province].[Washington],

[Geography].[Geography].[City].[Bellevue],
[Geography].[Geography].[City].[Bellingham],

[Geography].[Geography].[City].[Lacey],
[Geography].[Geography].[City].[Seattle]},

{[Geography].[Geography].[State-Province].[Washington]}) ON AXIS(1)
```

This row specification, within a proper query executed against the Adventure Works sample cube that, say, stipulated the Reseller Sales Amount measure on the column axis, for calendar year 2003 might produce a results dataset similar to that depicted in Illustration 1.

Illustration 1: Results Dataset – Washington Cities Drilled Up to State Level

In the example dataset, we see that California and Washington (the top and bottom rows of the returned dataset) are presented in "rolled up" state. Underneath California's summary line, we see the values for the constituent child cities. We do not see the cities that contribute to the Washington summary line appear, however. This is because we have specified Washington as the secondary set within the DrillUpMembers() function employed in the snippet above. Because the State of Washington is the immediate ancestor of the four Washington cities we specify in the snippet, the function drills up to the State level for those cities, and presents the summary for Washington alone.

We will practice a use of the DrillUpMember() function in the section that follows.